2011-01-06 19 views
5

Die folgende scala Code scheint gültig zu sein:Fehler in Scala Typ-System?

class A[X] 
class C[M[X] <: A[X]] 

class Main 

new C[A] 

ich den Compiler erwartet Typinferenz auf Typ A auszuführen, aber nachdem ich die folgende versucht:

new C[A[Int]] 

bekam ich die folgende Fehlermeldung :

(fragment of Main.scala):11: error: this.A[Int] takes no type parameters, expected: one 
println(new C[A[Int]]) 

Antwort

2

Sie haben nicht erklären X als Typ-Parameter für C. Versuchen Sie Folgendes:

class C[X, M[X] <: A[X]] 
+0

wird dies auch nicht funktionieren. Das Problem ist, dass C einen Typ mit einem Typparameter erwartet. Wenn Sie versuchen, das neue C [A] auszuprobieren, wird dies funktionieren, da A ein Typargument benötigt. – tim

+0

Dies funktioniert nicht - C erwartet nun zwei Typparameter. – gpampara

6

Versuchen Sie diese Syntax.

class C[M <: A[_]] 

Dies bedeutet, dass C eine Klasse ist, die ein Typ-Parameter hat, die eine Unterklasse von A sein sollte, und nimmt einen Typ-Parameter.

15

Mal sehen, was das bedeutet in Plain Englisch.

bedeutet: Lassen Sie A eine Klasse sein, die einen Typparameter akzeptiert.

class C[M[X] <: A[X]] 

bedeutet: Sei C eine Klasse sein, die einen Typ-Parameter annimmt, die eine Klasse sein sollen, dass ein Typ-Parameter übernimmt und, parametriert, ist eine Unterklasse der Klasse A parametriert mit dem gleichen Typ.

Wenn Sie schreiben

new C[A] 

Sie sagen: eine Instanz von C erstellen mit A als Parameter. Entspricht A den oben genannten Kriterien? Ja, es ist eine Klasse, die einen Typparameter benötigt und parametrisiert ist eine Subklasse von ihr parametrisiert.

Wenn Sie jedoch schreiben

new C[A[Int]] 

der Typparameter Sie versuchen, C, A [Int] zu geben, entspricht nicht den Kriterien: A [Int] keine Typparameter übernimmt, was der Compiler Ihnen freundlich sagt. (Und es ist auch keine Unterklasse von A [X].)

+1

Dies ist die richtige Antwort; Die einzige Sache, die ich hinzufügen würde (um bei Websuchen zu helfen), ist, dass dies ein Beispiel für einen höher-kinded Typ ist, wo der Typparameter zu C mit art * -> * bezeichnet wird. A [Int] dagegen hat einfach Art *. –

+0

Meinst du "A" statt "C"? 'A [Int]' hat die Art '*', aber A sollte '* -> *' sein, nein? Dann sollte "C" '(* -> *) -> *' sein? – Emre

0

Sie wollen Ihre Klasse nicht nehmen, um einen Typ-Parameter zu nehmen, Sie wollen es zwei nehmen! Zwei mögliche Lösungen:

class A[X] { 
    type T = X 
} 
class C[M <: A[_]] { 
    //use M#T if you want the type T was parameterized with. 
} 

Oder können Sie tun:

class A[X] 
class C[T, M[A] <: A[A]] { 
    //when you want the type, write M[T], not M. 
} 

JEDOCH, was Sie wollen wahrscheinlich ist dies:

class A[X] 
class C[M <: A[_]] 
+0

Um es einfacher zu machen, ist dies das Äquivalent in Java: Klasse A {...} // für alle. Klasse C > {...} // zuerst. nicht perfekt. // Sekunde ist nicht möglich. – Anonymous

1

Es ist alles here erklärt, konzentrieren sich auf die „Common Fallstricke "Abschnitt, weil es ziemlich TLTR ist.