我是否必须在子类型中指定类型方差?

时间:2017-06-12 10:47:18

标签: scala

让我们说我有一个特质

sealed trait Expr[-InT, +OutT] {
  def apply(lhs: InT): OutT
}

我想在And中创建一个子类型InT逆变。我必须实现它(1):

type BExpr[-InT] = Expr[InT, Boolean]

final case class And[-InT](exp: BExpr[InT], exps: BExpr[InT]*) extends BExpr[InT] {
  def apply(lhs: InT) = exps.foldLeft(exp.apply(lhs))(_ & _(lhs))
}

或者以下是否足够(2)?

type BExpr[InT] = Expr[InT, Boolean]

final case class And[InT](exp: BExpr[InT], exps: BExpr[InT]*) extends BExpr[InT] {
  def apply(lhs: InT) = exps.foldLeft(exp.apply(lhs))(_ & _(lhs))
}

由于

1 个答案:

答案 0 :(得分:3)

好吧,让我们做一点测试。

scala> trait A[+T]
defined trait A

scala> trait B[T] extends A[T]
defined trait B

scala> def b1: B[String] = ???
b1: B[String]

scala> def b2: B[AnyRef] = b1
<console>:13: error: type mismatch;
 found   : B[String]
 required: B[AnyRef]
Note: String <: AnyRef, but trait B is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
       def b2: B[AnyRef] = b1
                           ^

scala> def a: A[AnyRef] = b1
a: A[AnyRef]

scala> trait B[+T] extends A[T]
defined trait B

scala> def b3: B[String] = ???
b3: B[String]

scala> def b4: B[AnyRef] = b3
b4: B[AnyRef]

所以是的它确实有所作为。如果您想将您的子类型公开给世界,而不是将其作为私有内部实现,那么添加适当的方差注释可能更好。