scala - 类型别名中的方差注释

标签 scala alias variance

最近我注意到方差注释可以在类型别名中使用。以下是来自 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/

相关文章:

xml - 删除 scala 中的前缀属性 (scala-xml)

mysql - 带有前导空格的列别名导致错误 : Unknown column 'BAR. COL1' in 'field list'

git - 如何重命名自定义 Git 别名?

时间窗口不恒定时的运行方差

R,基于方差截止的滤波器矩阵

sql - 计算sqlite中的方差

Scala SBT - sbt-native-packager,如何指定自定义阶段目录

scala - 在 Scala 中获取有关 case 类字段的完整信息

scala - 你如何缩进scaladoc的代码块

MySQL别名简写?