2016-06-18 22 views
0

Unter der Annahme, dass ich eine Funktion, die implizite TypeTag definiert nimmt: esWie macht man die Inferenz von Scala, die stark genug ist, um generische Typparameter zu entdecken?

def andOptionFn[A: TypeTag](g: Int => Option[A]) = { 
    val ttg = ScalaReflection.universe.typeTag[A] 
    println(ttg) 
    ... 
    } 

Und rufen:

andOptionFn{ 
v => 
    Some(v) 
} 

Ich würde erwarten, scala Typinferenz bekommen den richtigen Typ TypeTag (Option (Int)), aber stattdessen bekam ich:

TypeTag(Option(Any)) (not even a higher kind) 

Warum Scala ist nicht in der Lage, automatisch in Kompilierungszeit abzuleiten? Und was muss getan werden, um es zu verbessern?

Antwort

1

Das richtige Ergebnis ist TypeTag[Int] und Scala tut es drucken: http://scastie.org/20273 (nachdem Sie ScalaReflection mit scala.reflect.runtime ersetzen, wenn ScalaReflection Ihre eigene Klasse ist, das ist, wo Sie für das Problem aussehen sollte).

EDIT: http://scastie.org/20293 ist kein Fehler, es ist Typ Inferenz verhält sich genau wie vorgesehen. Call to Seq.apply[Option[_]] gibt den erwarteten Typ von Option[_] zu jedem Argument. Wenn

andOptionFn { 
    v => 
    if (v > 1) Some(v) 
    else None 
} 

mit diesem erwarteten Typ typechecked wird, ist die abgeleitete R natürlich Any.

EDIT 2: Nach dem Lesen http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#local-type-inference sorgfältiger, es scheint, als ob es schließlich Int ableiten sollte, aber ich bin mir nicht sicher. Was ich dachte ist, dass Option[_] auf Option[Any] reduziert wird (weil Option kovariant ist), in diesem Fall sollte Any sicher abgeleitet werden. Aber http://scastie.org/20293 undsollte sich gleich verhalten, also gibt es mindestens einen Fehler (glaube ich) :)

+0

Sorry, in der Tat wurde das Problem, auf das ich stieß, von etwas anderem verursacht: Es ist ein Fehler im Compiler-Typ Inferenz, die immer noch nicht wurde gelöst: siehe das Ergebnis in http://scastie.org/20293 für einen kurzen Blick – tribbloid

+0

Zum Vergleich, siehe 2 etwas andere Fälle: http://scastie.org/20294 und http://scastie.org/20295 – tribbloid

+0

die Das Problem wird dadurch verursacht, dass andOptionFn in eine andere Funktion eingebunden wird, die den generischen Typparameter akzeptiert. Sehr komplizierter Bug oder? – tribbloid