为什么在向类型引入参数后,这将停止工作?(斯卡拉)

  • 本文关键字:停止工作 类型 参数 scala
  • 更新时间 :
  • 英文 :


我正在使用这个程序

abstract class Foo[+T[_]] {}
case object Unit extends Foo
case class Cons[+T[_]](a: Foo[T], b: Foo[T]) extends Foo[T]
case class Strings[T[_]](x: T[String]) extends Foo[T]
def first[T[_]](v: Foo[T]): Option[Foo[T]] = v match {
case Cons(a, b) => Some(a)
case _ => None
}

并收到错误

constructor cannot be instantiated to expected type;
found   : Cons[T]
required: Foo[?T1] where type ?T1 <: T (this is a GADT skolem)

但是,如果我摆脱了T参数,它就可以正常工作了?

abstract class Foo[+T] {}
case object Unit extends Foo
case class Cons[+T](a: Foo[T], b: Foo[T]) extends Foo[T]
case class Val[T](x: T) extends Foo[T]
def first[T](v: Foo[T]): Option[Foo[T]] = v match {
case Cons(a, b) => Some(a)
case _ => None
}

这是因为FooCons的协方差。如果你删除+,一切都会编译。在协变情况下,当你将Foo[T]类型的v与模式匹配时Cons(a, b)这个a不一定是具有相同TFoo[T]类型,a可以是任何类型,Foo[T']T' >: T(或Foo[Any]),这与返回类型相矛盾。使用自定义unapply您可以消除类型的这种不确定性。

我似乎可以通过提供自己的Cons.unapply来解决这个问题。我不清楚为什么我需要写自己的。

object Cons {
def unapply[T[_]](v: Foo[T]): Option[(Foo[T], Foo[T])] = {
if(v.isInstanceOf[Cons[T]]) {
v.asInstanceOf[Cons[T]] match {
case Cons(a,b) => Some((a,b))
case _ => None
}
} else {
None
}
}
}

相关内容

最新更新