假设是这样:
// applying some other minor changes...
sealed trait Vector[A] {
type ThisButType[B] <: Vector[B]
def zip[B](other: ThisButType[B]): ThisButType[(A, B)]
}
case class Term[A]() extends Vector[A] {
override type ThisButType[B] = Term[B]
override def zip[B](other: Term[B]): Term[(A, B)] = Term()
}
case class Component[A, T <: Vector[A]](value: A, tail: T) extends Vector[A] {
override type ThisButType[B] = Component[B, T#ThisButType[B]]
override def zip[B](other: Component[B, T#ThisButType[B]]): Component[(A, B), T#ThisButType[(A, B)]] =
Component((value, other.value), tail.zip(other.tail.asInstanceOf[tail.ThisButType[B]]))
}
然后……
val zero = Term[Unit]()
val zero0: Vector[Unit]#ThisButType[Int] = Term[Int](): zero.ThisButType[Int] // the mystical double type ascription!
val two = Component((), Component((), Term[Unit]()): Vector[Unit])
two.zip(Component(0, zero0)) // ClassCastException!
因此,您的代码确实存在类型错误,编译器将其视为错误而拒绝是正确的。具体来说,您的代码中的T#ThisButType[B] 与tail.ThisButType[B] 完全不相同,因为tail 不必是精确类型T,但可以是某个子类型。在这种情况下,T#ThisButType[B] 可以包含 tail.ThisButType[B] 不包含的值,这意味着您不能将前者 (other.tail) 传递给需要后者的函数 (tail.zip)。
故事的寓意:类型投影是邪恶的,应该避免。你有一个非常好的价值 tail: T 就在那里;只是从那个项目。
// applying some more minor changes...
sealed trait Vector[+A] {
type ThisButType[+B] <: Vector[B]
def zip[B](other: ThisButType[B]): ThisButType[(A, B)]
}
case object Term extends Vector[Nothing] {
override type ThisButType[+B] = Term.type
override def zip[B](other: Term.type): Term.type = Term
}
case class Component[+A, +T <: Vector[A]](value: A, tail: T) extends Vector[A] {
override type ThisButType[+B] = Component[B, tail.ThisButType[B]]
override def zip[B](other: Component[B, tail.ThisButType[B]]): Component[(A, B), tail.ThisButType[(A, B)]] =
Component((value, other.value), tail.zip(other.tail))
}
之前的例子不再有效:
val zero: Vector[Unit]#ThisButType[Int] = Term: Term.ThisButType[Int]
val two = Component((), Component((), Term): Vector[Unit])
two.zip(Component(0, zero)) // fails: don't know that zero: two.tail.ThisButType[Int]
现在代码是正确的。