如何表达高阶类型的类型约束

fhu*_*usb 8 types scala

我正在尝试创建一个使用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))
}
Run Code Online (Sandbox Code Playgroud)

所以我在这里尝试创建符合B特征的对象列表.但是,此代码将无法编译,并给出以下错误:

类型参数(B)的种类不符合预期种类的类型参数(类型X).B的类型参数与类型X的预期参数不匹配:类型Y的边界>:Nothing <:A [Y]比类型_的声明边界更严格>:Nothing <:Z forSome {type Z <:A [Z]} val myList = emptyList [B]()

对我来说,它似乎_ <: Z forSome { type Z <: A[Z] }确实至少同样严格,Y <: A[Y]但也许我错过了一些东西.

所以问题是 - 对于正确处理B的emptyList函数应该有什么约束?

Kip*_*ros 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))
}
Run Code Online (Sandbox Code Playgroud)