2012-05-16 12 views
6

Ich versuche, einige Methoden mit sehr allgemeinen Typparametern zu parametrisieren.Scala-Typen: am wenigsten obere Grenzen

Als Beispiel in der REPL definiere ich zuerst:

trait Term 
case class FunctionalTerm[+T <: Term](t: T) extends Term 

Intuitiv nimmt das folgende Verfahren eine Laufzeit und eine FunctionalTerm und gibt etwas mit Typ der oberen Grenze der Art des Ausdrucks übergeben und der Argumenttyp des FunctionalTerm:

So weit so gut in der REPL.

Dann definiere ich ex2 als eine Komfortfunktion, die die gleiche Operation wie ex1 durchführt, aber mit den Eingangsargumente vertauscht:

def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2,s) 

Versuch ex2 im REPL ergeben folgende Fehler zu definieren:

error: inferred type arguments [T2,T3,FunctionalTerm,T3,T3] do not conform to method ex1's type parameter bounds [T1 <: Term,T3 <: X,FunctionalTerm[T1] <: X,X <: R,R <: Term] 
     ex1(t2,s) 
     ^
error: type mismatch; 
found : FunctionalTerm[T2] 
required: FunctionalTerm[T1] 
     ex1(t2,s) 
      ^
error: type mismatch; 
found : T3(in method ex2) 
required: T3(in method ex1) 
     ex1(t2,s) 
       ^
error: type mismatch; 
found : R(in method ex1) 
required: R(in method ex2) 
     ex1(t2,s) 
      ^

Ich habe etwa zwei Tage damit verbracht, eine Lösung zu finden, und bin jetzt völlig festgefahren. Ich kann bei Google nichts mehr finden.

Da der Typ Argumentliste von ex2 ist die gleiche wie die von ex1 aber mit T1 und T2 getauscht, die ich nicht verstehe, ist falsch, oder wie man es beheben.

Jede Hilfe würde sehr geschätzt werden!

aktualisieren

Least obere Schranken waren eine falsche Fährte. Das Beispiel kann weiter destilliert werden.

die folgenden beiden Funktionen können in der REPL ohne Fehler definiert werden:

def ex1[T1 <: Term, FunctionalTerm[T1] <: Term](t1: FunctionalTerm[T1]): Term = sys.error("TODO: ex1") 
def ex2[T2 <: Term, FunctionalTerm[T2] <: Term](t2: FunctionalTerm[T2]): Term = ex1(t2) 

die zusätzlichen Parameter Einführung X das Problem zu verursachen scheint.

def ex3[T1 <: Term, FunctionalTerm[T1] <: X, X <: Term](t1: FunctionalTerm[T1]): Term = sys.error("TODO: ex3") 

Aber versuchen, anschließend definieren:: Ich kann die folgende in der REPL definieren

def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 

den Fehler gibt:

error: inferred type arguments [T2,FunctionalTerm,Nothing] do not conform to method ex3's type parameter bounds [T1 <: Term,FunctionalTerm[T1] <: X,X <: Term] 
     def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 
                          ^
error: type mismatch; 
found : FunctionalTerm[T2] 
required: FunctionalTerm[T1] 
     def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 
                           ^

Also, ich denke, die Frage wird: Warum tut Der in der Signatur nicht verwendete Parameter X hat diesen Effekt?

+0

Ich habe vergessen zu sagen, dass ich Scala bin mit 2,10-M3. –

+0

Du verwendest jedoch keine höheren Arten :-) –

+0

@oxbow_lakes Oh ... Ich werde korrigieren –

Antwort

5

Ich bin mir nicht sicher, ob Sie einen Fehler haben oder nicht, aber ich bin ziemlich sicher, dass Sie Ihr Leben viel schwieriger machen, als es sein muss. Sie können auf Kovarianz und Vereinigung verlassen Sie all die harte Arbeit zu tun,

scala> trait Term 
defined trait Term 

scala> case class FunctionalTerm[+T <: Term](t: T) extends Term 
defined class FunctionalTerm 

scala> def ex1[T <: Term](t1 : FunctionalTerm[T], s : T) : T = s 
ex1: [T <: Term](t1: FunctionalTerm[T], s: T)T 

scala> class A extends Term ; class B extends A ; class C extends A 
defined class A 
defined class B 
defined class C 
scala> ex1(new FunctionalTerm(new B), new C) 
res0: A = [email protected] 

Hinweis den abgeleitete Ergebnistyp (das die R Ihre ursprünglichen komplexere Definition entspricht) ... es ist A, die das ist LUB von B und C.

Nun ist die blätterte Version ist trivial und einfach Works,

scala> def ex2[T <: Term](s : T, t1 : FunctionalTerm[T]) : T = s 
ex2: [T <: Term](s: T, t1: FunctionalTerm[T])T 

scala> ex2(new C, new FunctionalTerm(new B)) 
res1: A = [email protected] 
+1

Es stellt sich heraus, dass das gemeldete Verhalten KEIN Fehler ist. Mit FunctionalTerm [T1] <: X und FunctionalTerm [T2] <: X wurde im ursprünglichen Beispiel ein Methodentypparameter namens "FunctionalTerm" deklariert, der nicht mit der gleichnamigen Fallklasse in Zusammenhang steht. Ich bezeichne dies jedoch als die Antwort, denn was vorgeschlagen wurde, hat erreicht, was ich tun musste. –

+0

Gut duh! ... erstaunlich, dass weder ich noch @oxbow_lakes das bemerkt haben! –

2

Ich werde dein Beispiel vereinfachen (ich verwende 2.9.1):

scala> trait Term; case class FunctionalTerm[+T <: Term](t: T) extends Term; 
defined trait Term 
defined class FunctionalTerm 

scala> def ex1[T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3): R = sys.error("TODO") 
ex1: [T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3)R 

nun die zweite Methode erklärt:

scala> def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2, s) 
<console>:11: error: inferred type arguments [T2,T3,FunctionalTerm,T3,T3] do not conform to method ex1's type parameter bounds [T1 <: Term,T3 <: X,FunctionalTerm[T1] <: X,X <: R,R <: Term] 
     def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2, s) 
                                ^

Die verdächtig Sache (für mich) ist der abgeleitete Typ [T2,T3,FunctionalTerm,T3,T3] - insbesondere FunctionalTerm. FunctionalTerm ist ein Typkonstruktor* -> * aber die Methode erwartet einen Typ * in dieser Position.

Ich würde sagen, dass dies (vermutlich) ein Fehler und daher sollten Sie es an die scala-Benutzer-Mailingliste einreichen (vor einem Ticket Anheben) - Adriaan Moors und Miles Sabin sind viel eher haben eine detaillierte Antwort, ob ich recht habe.

+0

Vielen Dank - ich vermutete, dass es ein Käfer war, aber mein begrenztes Wissen über Typen machte mich vorsichtig. Ich werde aktualisieren, wenn ich etwas gelöst habe. –

Verwandte Themen