如何理解“方法参数的方差位置与封闭参数子句的方差位置相反。”

时间:2014-05-02 11:39:42

标签: scala type-systems

我看到这句话是scala specification (pdf)

  

方法参数的方差位置与封闭参数子句的方差位置相反。

这是第44页。

但我不太明白。你能给我一些样品吗?

1 个答案:

答案 0 :(得分:7)

所以,让我们从一个激励性的例子开始吧。假设我写了以下内容:

class Foo[+A] {
  def foo(a : A) = ???
}

现在,通过使用A注释类型参数+,我已声明Foo中的A是协变的,也就是说,如果X <: Y,然后是Foo[X] <: Foo[Y]。所以,假设我有这样的Foo[X],我尝试将其传递给需要Foo[Y]的函数:

def bar(a : Y, x : Foo[Y]) = {
  x.foo(a)
}

现在,bar尝试使用x.foo致电Y。但是xFoo[X]XY的子类型 - 所以它就像尝试将Object传递给需要的函数一样String - Object无法保证Foo包含执行此操作所需的所有内容。因此上面A的定义无效 - 要在规范中使用术语,类型参数Foo是协变的,但您已尝试在逆变位置中使用它/ em> - 作为函数的参数。

您引用的Scala规范中规定的规则集是Scala编译器用来确定代码中不同位置的方差位置的规则,它使用检查您是否还没有完成上述class Foo[A, B] { def foo(a : A) = { def bar(b : B) = ??? } } 的定义。您标识的特定子句给出了与上面示例相对应的规则 - 它表示参数子句的方差位置(例如,在函数的参数列表中)与周围的方差位置相反。

通常,这意味着参数子句是逆变的。然而,事情可以多次倒转:

foo

这里,bar的参数子句是逆变的,因此class Foo[-A, +B] { def foo(a : A) = { def bar(b : B) = ??? } } 的参数子句再次被反转,并且是协变的。所以以下定义是有效的:

{{1}}