最近我注意到方差注释可以在类型别名中使用。以下是来自 Predef
的示例:
type Function[-A, +B] = Function1[A, B]
我开始思考它可以用在哪里。显然,您不能将方差更改为相反,或者使不变类型表现为协变或逆变。编译器会抛出一个错误,像这样
scala> type BrokenFunc[+T, -R] = Function1[T, R]
<console>:7: error: covariant type T occurs in contravariant position in type
[+T, -R]T => R of type BrokenFunc
但是,您可以使某些变体类型表现得像不变的(至少,编译器不会反对这一点)。因此,我尝试制作 List
scala> type InvList[T] = List[T]
defined type alias InvList
但是这个新的不变 List
的行为仍然就像它的原始协变版本一样:
scala> val l: InvList[String] = List("foo")
l: InvList[String] = List(foo)
scala> val anyList: InvList[Any] = l
anyList: InvList[Any] = List(foo)
那么,我缺少什么?类型别名中差异注释的目的是什么?您能否给出一个带有方差注释的类型别名的示例,它将与原始类型不同。
最佳答案
所以,我不确定,但我将提供一个可能的解释。
Scala 中的类型别名相当“弱”;他们并没有完全创建新类型,只是编写旧类型(以及新的路径依赖类型)的新方法;这意味着如果您定义
type InvList[T] = List[T]
并写下InvList[T]
,就像你写的 List[T]
一样;这就是为什么InvList[Int] <: InvList[Any]
,因为重写后,这只是 List[Int] <: List[Any]
。我实际上不确定 Scala 类型别名究竟有多“弱”……由于路径依赖类型,它们比 Haskell 的别名强一点,但比类声明弱。也许其他人可以进一步解释。
那么,如果 Scala 只是忽略它们并重写类型,为什么它允许您在其中放置差异注释呢?它适用于类型成员。这样你就可以说
trait A { type F[+T] }
并要求实现符合+T
差异,以便您允许
trait B extends A { type F[+T] = List[T] }
但不是
trait C extends A { type F[T] = Function[T,T] }
或者,就像 Scala Language Spec S4.3 中的这句话一样.
A type constructor declaration imposes additional restrictions on the concrete types for which t may stand. Besides the bounds L and U , the type parameter clause may impose higher-order bounds and variances, as governed by the conformance of type constructors (§3.5.2).
关于scala - 类型别名中的方差注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10523199/