2012-11-02 10 views
8

Ich versuche, eine Liste einiger Merkmale zu erstellen, die durch einen Typ unter Verwendung des CRTP parametrisiert werden, und kann nicht herausfinden, wie die Typabhängigkeiten ausgedrückt werden. Hier ist ein Beispielcode, der das Problem veranschaulicht:So geben Sie Typeinschränkungen für höherwertige Typen aus

trait A[X] { 
    def x: X 
} 

trait B[Y <: A[Y]] { 
    def y(i: Int): Y 
} 

case class C(i: Int) extends A[C] { 
    def x = C(i) 
} 

case class D(i: Int) extends A[D] { 
    def x = D(i) 
} 

case class E() extends B[C] { 
    def y(i: Int) = C(i) 
} 

case class F() extends B[D] { 
    def y(i: Int) = D(i) 
} 

object Program extends App { 
    def emptyList[X[_ <: Z forSome { type Z <: A[Z] } ]]() = collection.mutable.ListBuffer.empty[X[_]] 

    val myList = emptyList[B]() 
    myList += E() 
    myList += F() 

    println(myList.map(_.y(2).x)) 
} 

Also hier Ich versuche, eine Liste von Objekten zu erstellen, die auf die B Merkmal entsprechen. Allerdings wird dieser Code nicht kompiliert werden, und gibt den folgenden Fehler:

kinds of the type arguments (B) do not conform to the expected kinds of the type parameters (type X). B's type parameters do not match type X's expected parameters: type Y's bounds >: Nothing <: A[Y] are stricter than type _'s declared bounds >: Nothing <: Z forSome { type Z <: A[Z] } val myList = emptyList[B]()

Mir scheint es wie _ <: Z forSome { type Z <: A[Z] } als Y <: A[Y] in der Tat mindestens so streng ist, aber vielleicht bin ich etwas fehlt.

Die Frage ist also - was sollten die Einschränkungen auf der emptyList-Funktion sein, um B korrekt zu behandeln?

+1

Ich denke, das Problem hier ist, dass das, was Sie wirklich wollen, sagen 'X [_ Submonoid

Antwort

4

Nach ein paar Versuch und Irrtum, habe ich es zur Arbeit. Hinweis: Der Compiler sagt uns, dass die Typparameter in A [+ X] und B [+ Y] kovariant sein müssen.

trait A[+X] { 
    def x: X 
} 

trait B[+Y <: A[Y]] { 
    def y(i: Int): Y 
} 

case class C(i: Int) extends A[C] { 
    def x = C(i) 
} 

case class D(i: Int) extends A[D] { 
    def x = D(i) 
} 

case class E() extends B[C] { 
    def y(i: Int) = C(i) 
} 

case class F() extends B[D] { 
    def y(i: Int) = D(i) 
} 


object Test extends App { 
    def emptyList[X[Y <: A[Y]]] = collection.mutable.ListBuffer.empty[X[Y forSome {type Y <: A[Y]} ]] 

    val myList = emptyList[B] 
    myList += E() 
    myList += F() 

    println(myList.map(_.y(2).x)) 
} 
+0

Ich habe auch Kovarianzeinstellungen versucht, aber es ist nicht gelungen, die emptyList-Methode korrekt zu machen. Danke, dass du das herausgefunden hast. – fhusb

Verwandte Themen