Ich stieß auf ein rätselhaftes Inferenzproblem mit Fallklassen. Hier ist ein minimales Beispiel:Scala-Muster entspricht "Any" anstelle eines existentiellen Typs, bricht Typ Sicherheit?
trait T[X]
case class Thing[A, B, X](a: A, f: A => B) extends T[X]
def hmm[X](t: T[X]) = t match {
case Thing(a, f) => f("this really shouldn't typecheck")
}
Scala entscheidet, dass a: Any
und f: Any => Any
, aber das ist unpassend; sie sollten wirklich die Typen a: SomeTypeA
und f: SomeTypeA => SomeTypeB
haben, wobei SomeTypeA
und SomeTypeB
unbekannte Typen sind.
Ein anderer Weg, dies zu sagen ist, dass ich die hypothetische Thing.unapply
Methode denken, so etwas wie
def unapply[X](t: T[X]): Option[(A, A => B)] forSome { type A; type B } = {
t match {
case thing: Thing[_, _, X] => Some((thing.a, thing.f))
}
}
richtig einen Typfehler gibt an f("this really shouldn't typecheck")
Diese Version aussehen sollte.
Scheint dies ein Fehler im Compiler, oder fehlt mir etwas?
Edit: Dies ist auf Scala 2.10.3.
Scala zu geben hat 'A' und 'B' einen Typ, so welche Art sollte es sie geben, da Sie nicht angegeben, was die Typen sein sollte? – Noah
Nun, ich bin mir nicht sicher, aber die benutzerdefinierte 'unapply'-Methode funktioniert korrekt. Der Compiler verfolgt die Tatsache, dass 'a' und' f' verwandte Typen haben. –
Ich stimme @Noah zu, ohne etwas auf den Compiler zu gehen sollte Standard auf Any. Aber ich sehe, wie das potenziell gefährlich sein könnte. –