scala中的协方差和方差翻转

opt*_*nal 7 type-systems scala

斯卡拉为不耐烦据说

函数在其参数中是反变量的,在结果类型中是协变的

这是直截了当且易于理解的,但它在同一主题中说

但是在函数参数内部,方差翻转 - 其参数是协变的

它以IteratorfoldLeft方法 为例:

 def foldLeft[B](z : B)(op : (B, A) => B) : B 
Run Code Online (Sandbox Code Playgroud)

我不清楚它说的是什么.

我试过一些博客

  1. http://www.artima.com/pins1ed/type-parameterization.html

  2. http://blog.kamkor.me/Covariance-And-Contravariance-In-Scala/

  3. http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

但没有得到明确的理解.

opt*_*nal 4

函数的参数类型始终是逆变的,返回类型是协变的,例如

trait Function1[-T1, +R] extends AnyRef 

trait Function2[-T1, -T2, +R] extends AnyRef 
Run Code Online (Sandbox Code Playgroud)

这里,T1, T2, ..., Tn (其中 n <= 22)是参数,R是返回类型

在高阶函数(将函数作为参数的函数)中,参数可以具有传递给函数的类型参数,例如 foldLeft在特征中Iterable

Iterable被声明为

trait Function1[-T1, +R] extends AnyRef 

trait Function2[-T1, -T2, +R] extends AnyRef 
Run Code Online (Sandbox Code Playgroud)

并被foldLeft标记为

trait Iterable[+A] extends AnyRef
Run Code Online (Sandbox Code Playgroud)

由于A声明为协变,因此可以将其用作返回类型。但这里它是一个参数类型,因为

def foldLeft[B](z : B)(op : (B, A) => B) : B 
Run Code Online (Sandbox Code Playgroud)

因为op : (B, A) => B是 的字面类型Function2

关键是特征Function2在其参数类型上是逆变的

因此,协方差类型出现在方法参数中,因为

Trait Function2 的参数类型是逆变的

这称为方差翻转

  1. 协方差的翻转就是逆变。
  2. 逆变的翻转就是协变。
  3. 翻转是不变的就是不变的。

这就是为什么不变量可能出现在任何位置(协变/逆变)