Scala: generische gewichtete Durchschnittsfunktion

8

Ich möchte eine allgemeine gewichtete Durchschnittsfunktion implementieren, die die Anforderungen an die Werte und die Gewichte vom gleichen Typ lockert. dh ich möchte Sequenzen von sagen: (value:Float,weight:Int) und (value:Int,weight:Float) Argumente und nicht nur: (value:Int,weight:Int) . [Siehe meine früheren Frage in diesem Vorfeld .]

Das habe ich zur Zeit:

%Vor%

Das funktioniert perfekt, wenn ich es zum Beispiel füttere:

%Vor%

Allerdings, wenn ich die Gewichte nicht von Int auf Float "upcast":

%Vor%

Scala-Compiler wird mir sagen:

  

error: konnte keinen impliziten Wert für den evidence-Parameter des Typs finden   Numerisch [AnyVal]
  val avg = gewichtete Mittel (Werte)

Gibt es eine Möglichkeit, dies zu umgehen?

Ich hatte einen Versuch, eine NumericCombine Klasse zu schreiben, die mich mit% parametriert co_de% und A der „verbindet“ die Typen in einen „gemeinsamen“ Typen B (zum Beispiel der Kombination AB und Float gibt dir Int ):

%Vor%

und ich schaffte es einfach zu schreiben Float und times Funktionen basierend auf dieser mit dem typeclass Muster, aber seit plus führt ein pfadabhängigen Typ NumericCombine , „komponieren“ die Typen erweist sich mehr zu sein Schwieriger als ich erwartet hatte. Blick auf diese Frage für weitere Informationen und Hier finden Sie hier für die vollständige Implementierung von AB .

Aktualisieren

Eine etwas befriedigende Lösung wurde als Antwort auf hier ) aber es gibt noch Raum für einige Designverbesserung berücksichtigt die in der Diskussion mit @ziggystar angesprochenen Punkte.

    
ShS 13.04.2017, 01:52
quelle

2 Antworten

3

Lineare Kombinationen

Ich denke, die allgemeinere Aufgabe, bei der einige Elemente vom Typ T mit einem Skalar vom Typ S gewogen / skaliert werden, ist der einer linearen Kombination. Hier sind die Einschränkungen für die Gewichte für einige Aufgaben:

Der allgemeinste Fall nach dieser Klassifizierung ist also die Linearkombination. Nach Wikipedia müssen die Gewichte S ein Feld und T einen Vektorraum über S .

Bearbeiten: Die wirklich allgemeinste Anforderung, die Sie für die Typen haben können, ist, dass T ein Modul (Wiki) über den Ring S , oder T ist ein S -Modul.

Spire

Sie können diese Anforderungen mit typeclasses einrichten. Es gibt auch einen Turm , der bereits Typklassen für Field und VectorSpace enthält. Ich habe es nie selbst benutzt, also musst du es selbst ausprobieren.

Float / Int funktioniert nicht

Was aus dieser Diskussion hervorgeht und was Sie bereits beobachtet haben, ist die Tatsache, dass Float als Gewicht und Int als Elementtyp nicht funktionieren, da die ganzen Zahlen nicht gebildet werden ein Vektorraum über den Realen. Sie müssten Int zuerst auf Float hochladen.

Promotion über Typklasse

Es gibt nur zwei Hauptkandidaten für den Skalartyp, d. h. Float und Double . Und hauptsächlich ist nur Int ein Kandidat für die Werbung, also könntest du folgendes als einfache und nicht so allgemeine Lösung machen:

%Vor%     
ziggystar 19.04.2017 09:42
quelle
-1

Zuerst ist Ihre Vorlage falsch. (Und tut mir leid, wenn der Ausdruck "Vorlage" falsch ist - ich bin ein Neuling in Scala). Ihre Funktionen erwarten Tupel, bei denen beide Elemente vom selben Typ sind ([A: Numerisch]), anstelle von Tupeln, bei denen Elemente unterschiedlicher Typen sind ([A: Numerisch, B: Numerisch]) ((Int, Float) vs (Float, Float))

Wie auch immer, die unten stehenden Kompilationen werden hoffentlich funktionieren, nachdem Sie sie mit Ihrem gewünschten Kalkül gefüllt haben.

%Vor%     
Volty De Qua 21.04.2017 23:52
quelle