类型别名中的方差注释 [英] Variance annotations in type aliases

查看:123
本文介绍了类型别名中的方差注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我注意到可以在类型别名中使用差异注释。以下是 Predef 的示例:

Recently I've noticed that variance annotations can be used in type aliases. Here is example from Predef:

type Function[-A, +B] = Function1[A, B]

我开始思考,可以在哪里使用它。显然,您不能将方差更改为相反的值,也不能将不变类型的行为表现为协变或协变。编译器将引发错误,例如

And I started to think, where it could be used. Obviously, you can't change variance to opposite, or make an invariant type to behave as co- or contravariant. Compiler will throw an error, like this

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

的R

但是,您可以使某些变量类型表现得像不变式(至少,编译器不会反对)。因此,我尝试制作 List

scala> type InvList[T] = List[T]
defined type alias InvList

不变 List 仍然像原始协变版本那样运行:

But this new invariant List still behaves just like it's original covariant version:

scala> val l: InvList[String] = List("foo")
l: InvList[String] = List(foo)

scala> val anyList: InvList[Any] = l
anyList: InvList[Any] = List(foo)

那么,我想念的是什么?类型别名中的差异注释的目的是什么?您能否举一个带有差异注解的类型别名的示例,该示例将与原始类型有所不同。

So, what I am missing? What's the purpose of variance annotations in type aliases? Can you give an example of type alias with variance annotations, that will differ from original type.

推荐答案

所以,我没有肯定知道,但我将提供一个可能的解释。

So, I don't know for sure, but I'm going to offer a possible explanation.

Scala中的类型别名相当弱;它们不会完全创建新类型,而只是创建旧类型的新方法(以及新的依赖于路径的类型);这意味着如果您定义

Type aliases in Scala are fairly "weak"; they do not completely create new types, just new ways of writing the old types (and new path dependent types); this means that if you define

type InvList[T] = List[T]

并写 InvList [T] ,就好像您写了 List [T] ;这就是为什么 InvList [Int]< ;: InvList [Any] ,因为重写后的结果就是 List [Int]< ;: List [Any ] 。我实际上不确定到底Scala类型别名有多弱……由于路径相关的类型,它们比Haskell的强度要强一些,但比类的声明要弱。也许其他人可以进一步解释。

and write InvList[T], it is exactly as if you wrote List[T]; that's why InvList[Int] <: InvList[Any], because, rewritten, this is just List[Int] <: List[Any]. I'm not actually sure exactly how "weak" Scala type aliases are... they are a little stronger than Haskell's because of path-dependent types, but are weaker than class declarations. Maybe someone else can explain further.

那么,为什么Scala允许您在其中放置差异注释,如果它只是忽略它们并改写类型呢?适用于类型成员。这样就可以说

So, why does Scala allow you to put variance annotations in there, if it's just going to ignore them and rewrite the type anyway? It's for type members. It's so that you can say

trait A { type F[+T] }

,并要求实现符合 + T 的差异,以便您允许

and require that implementations conform to the +T variance, so that you allow

trait B extends A { type F[+T] = List[T] }

但不是

trait C extends A { type F[T] = Function[T,T] }

或者,从 Scala语言规范S4.3


类型构造函数声明对t可能代表的具体类型
施加了附加限制。除了边界L和U之外,类型参数子句
可能会施加更高阶的边界和方差,这受类型构造函数的一致性
约束(第3.5.2节)。

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).

这篇关于类型别名中的方差注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆