2012-11-02 4 views
8

CRTPを使用する型によってパラメータ化されたいくつかの特性のリストを作成しようとしており、型制約の表現方法を理解できません。問題を説明するサンプルコードを次に示します。より上位の種類の型制約を表現する方法

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)) 
} 

ここで、B特性に準拠したオブジェクトのリストを作成しようとしています。しかし、このコードはコンパイルして、次のエラー与えません。私には

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]()

_ <: Z forSome { type Z <: A[Z] }が実際Y <: A[Y]と少なくとも同じくらい厳しいですが、多分私は何かが欠けてるように思えます。

したがって、問題は、Bが正しく処理されるためには、emptyList関数で制約がどうなるでしょうか。

+1

ここで問題となるのは、あなたが本当に望むのは、X [_ <:Z forAll {type Z <:A [Z]}]です。私はこれを達成するためにどのように働いたのですか? – Submonoid

答えて

4

いくつかの試行錯誤の末、私はそれを動作させました。注意:コンパイラは、A [+ X]とB [+ Y]の型パラメータは共変でなければならないことを示しています。

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

共分散設定も試していましたが、emptyListメソッドを正しく取得できませんでした。それを考えてくれてありがとう。 – fhusb