为什么Scala中的类型参数列表中的所有不变泛型类位置都不变?

con*_*cat 5 generics scala invariance

我对下面的类型检查器的严格性感到有点困惑 - 似乎不变的T位置Inv[T]Variantish参数列表中也是不变的:

scala> class Inv[T]
defined class Inv

scala> class Variantish[+T, +TVar <: Inv[T]]
<console>:12: error: covariant type T occurs in invariant position in type  <: Inv[T] of type TVar
       class Variantish[+T, +TVar <: Inv[T]]
                             ^
Run Code Online (Sandbox Code Playgroud)

变体类型通常可以合法地出现在不变的参数列表位置,例如具有对象保护的可见性:

class Variantish[+T](protected[this] var v: Inv[T])
Run Code Online (Sandbox Code Playgroud)

并且似乎以下类似于类型安全:

class Variantish[+T, +TVar <: Inv[T]](protected[this] var v: TVar)
Run Code Online (Sandbox Code Playgroud)

需要上面提到的检查是如此严格?

Cyr*_*pet 1

从语言规范(强调我的),关于一致性(即T\'是 的超类型T):

\n\n
\n

输入构造函数TT\xe2\x80\xb2遵循类似的规则。我们通过它们的类型参数子句和来T表征和,其中或可以包括方差注释、高阶类型参数子句和界限。然后,符合 的有效类型参数的任何列表(带有声明的方差、边界和高阶类型参数子句)也是和的类型参数的有效列表。T\xe2\x80\xb2[a1,\xe2\x80\xa6,an][a\xe2\x80\xb21,\xe2\x80\xa6,a\xe2\x80\xb2n]aia\xe2\x80\xb2iTT\xe2\x80\xb2[t1,\xe2\x80\xa6,tn]T\xe2\x80\xb2TT[t1,\xe2\x80\xa6,tn]<:T\xe2\x80\xb2[t1,\xe2\x80\xa6,tn]

\n
\n\n

这确实很难理解(恕我直言),但我相信这意味着为了Variantish在 中保持协变T,你必须能够写

\n\n
Variantish[Dog, TVar] <: Variantish[Animal, TVar]\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于任何 TVar有意义的事情Variantish[Animal, TVar]。但这对于其中一些TVar,例如Inv[Animal]. 这就是为什么它在那个地方是被禁止的。

\n