I am trying to create a list of some trait, parameterised by a type using the CRTP, and cannot figure out how to express the type constraints. Here is some sample code that illustrates the problem:
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))
}
So here I'm trying to create a list of objects that conform to the B trait. However this code will not compile, and gives the following error:
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] ()
To me it seems like _ <: Z forSome { type Z <: A[Z] }
is indeed at least as strict as Y <: A[Y]
but maybe I'm missing something.
So the question is - what should the constraints be on the emptyList function to correctly handle B?
After some trial and error, I got it to work. Note: the compiler tells us that type parameters in A[+X] and B[+Y] must be covariant.
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))
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With