2013-12-03 3 views
7

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.

+0

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

+0

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. –

+0

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. –

Antwort

Verwandte Themen