例如
trait AA[+X[n], +Y] {
def x: X[Y] // [Error]: covariant type Y occurs in invariant position in type => X[Y] of method x
}
这似乎是错误的消息,因为X[Y]可以很容易地被证明是协变的:
如果Y1>:>Y2、+X1[n]>:>X2[n]对于所有n,则:
Y1>:>Y2
(X2的协方差)=>X2[Y1]>:>X2[Y2]
(X1[Y1]>:>X2[Y1])=>X1[Y1]>:>X2[Y2]
是什么原因导致了此错误消息?
您又缺少一个+
。正确的是
trait AA[+X[+n], +Y] {
def x: X[Y]
}
则类型X
将是协变的(相对于其类型参数n
)并且位置
def x: X[...]
// ^^^ <- this position
将是协变的,并且您将能够在该位置使用协变类型参数Y
。
相反,您声明了不变类型X
(w.r.t.n
),并试图在不变位置使用协变类型参数Y
。
有不同的概念:
协变/反变/不变类型参数(
+T
,-T
,T
)协变/反变/不变类型,即类型构造函数,相对于其类型参数(
T1 <: T2 => A[T1] <: A[T2]
、T1 <: T2 => A[T1] >: A[T2]
或它们中的任何一个)根据规则的协变/逆变/不变位置https://scala-lang.org/files/archive/spec/2.13/04-basic-declarations-and-definitions.html#variance-注释
+X[n]
是AA
的协变型参数,但相对于其类型参数n
是不变型。
以下结论不正确:
(X2的协方差)=>X2[Y1]>:>X2[Y2]
同样正确的做法是使Y
不变
trait AA[+X[n], Y] {
def x: X[Y]
}
顺便说一句,昨天Oleg Nizhnikov(@odomontois)进行了方差训练(以及其他主题)https://youtu.be/l08tK1x89ho?t=7494(从2:04:54开始)。