简体   繁体   English

为什么下限类型会改变方差位置?

[英]Why do lower type bounds change the variance position?

The Scala Language Specification (Section 4.5 on Variance Annotations, p. 44) says Scala语言规范(Variance Annotations第4.5节,第44页)

  • The variance position of a type parameter is the opposite of the variance position of the enclosing type parameter clause. 类型参数的方差位置与封闭类型参数子句的方差位置相反。
  • The variance position of the lower bound of a type declaration or type parameter is the opposite of the variance position of the type declaration or parameter. 类型声明或类型参数的下限的方差位置与类型声明或参数的方差位置相反。

Using the first point above, it is easy to see (at least formally) that 使用上面的第一点,很容易看到(至少正式)

trait Covariant[+A] {
  def problematic[B <: A](x : B)
}

produces the error message 生成错误消息

error: covariant type A occurs in contravariant position in type >: Nothing <: A of type B
       def problematic[B <: A](x : B)

and using the first and the second point it is easy to see that 并且使用第一点和第二点很容易看出

trait Contravariant[-A] {
  def problematic[B >: A](x : B)
}

produces the error message 生成错误消息

error: contravariant type A occurs in covariant position in type >: A <: Any of type B
             def problematic[B >: A](x : B)

As I mention, it's easy to see formally (ie, following the rules for variance annotations) why these errors occur. 正如我所提到的,很容易正式看到(即遵循方差注释规则)为什么会出现这些错误。 However, I can not come up with an example illustrating the need for these restrictions. 但是,我无法想出一个说明需要这些限制的例子。 In contrast, it is very easy to come up with examples that illustrate why method parameters should change variance positions, see eg Checking Variance Annotations . 相比之下,很容易想出说明为什么方法参数应该改变方差位置的例子,参见例如检查方差注释

So, my question is the following: Assuming, the two pieces of codes above were allowed, what are the examples of problems that arise? 所以,我的问题如下:假设,上面的两段代码被允许,出现问题的例子是什么? This means, I'm looking for examples similar to this one that illustrate what could go wrong in case the two rules cited above were not used. 这意味着,我正在寻找类似于这个的例子,说明如果不使用上面提到的两个规则会出现什么问题。 I'm particularly interested in the example involving lower type bounds. 我对涉及较低类型边界的示例特别感兴趣。

Note that the answer to Scala type bounds & variance leaves this particular question open, whereas the answer given in The "lower bound" will reverse the variance of a type, but why? 请注意, Scala类型边界和方差的答案会打开这个特定问题,而“下限”中给出的答案将反转类型的方差,但为什么呢? seems wrong to me. 对我来说似乎不对。

Edit: I think the first case can be handled as follows (adapting the example cited above). 编辑:我认为第一种情况可以如下处理(适应上面引用的例子)。 Assume, the following was allowed 假设,允许以下内容

trait Queue[+T] {
  def head : T
  def tail :  Queue[T]
  def enqueue[U <: T](x : U) : Queue[T]
}

Then we could implement 然后我们可以实施

class QueueImplementation[+T] extends Queue[T] {
  /* ... implement Queue here ... */
}

class StrangeIntQueue extends QueueImplementation[Int] {
  override def enqueue[U <: Int](x : U) : Queue[Int] = {
    println(math.sqrt(x))
    super.enqueue(x)
  }
}

and use it as 并用它作为

val x : Queue[Any] = new StrangeIntQueue
x.enqueue("abc")

which is clearly troublesome. 这显然很麻烦。 However, I can not see how to adapt this in order to show that the combination "contravariant type parameter + lower type bound" is also problematic? 但是,我看不出如何调整这个以表明“逆变型参数+下限类型”的组合也存在问题?

Use the ++ method from List to see why the restrictions are needed. 使用List++方法查看为什么需要这些限制。 Due note, this requires that ++ produce a List[B] : 需要注意的是,这需要++生成一个List[B]

 def ++[B](that: GenTraversableOnce[B]): List[B] 

with a full signature of 完整的签名

 def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That

So why is it important that [B >: A] . 那么为什么重要的是[B >: A] Well, what if we want to combine something such that 那么,如果我们想要结合这样的东西呢?

 trait Foo
 trait Bar extends Foo

and we have a method that has a signature 我们有一个有签名的方法

 def op(that: List[Foo], other: Foo): List[Foo] = that ++ List(other)

I can pass it a list of type Bar but in order to be able to return it as a List[Foo] I must make the condition that Foo >: Bar so that I can actually do the following 我可以传递一个类型为Bar的列表但是为了能够将它作为List[Foo]返回List[Foo]我必须使条件Foo >: Bar以便我可以实际执行以下操作

 def see(that: List[Bar]): List[Foo] = op(that, myFoo)

which essentially is doing a List[Bar] ++ List[Foo] to return a type of List[Foo] as expressed though a List[Foo] type. 它本质上是做一个List[Bar] ++ List[Foo]来返回一个List[Foo]类型,如List[Foo]类型所表达的那样。 That is why the flip happens. 这就是翻转发生的原因。

Now if I tried to enforce that Foo <: Bar I would immediately run into the issue that List[Bar] ++ List[Foo] could not return a list of type Foo (not to mention having it conflict with the definition above.) It would only ever be able to return a List of the least upper bound. 现在,如果我试图强制执行Foo <: Bar我会立即遇到List[Bar] ++ List[Foo]无法返回Foo类型列表的问题(更不用说它与上面的定义冲突了。)它只能返回最小上限的List

Let's suppose we allow for a class to have a type parameter [-T] and a method on that class to have [U >: T] ... 假设我们允许类具有类型参数[-T]并且该类的方法具有[U >: T] ...

for come class hierarchy
Dog <: Mammal <: Animal

class Contra[-X](x: X){
  def problem[Y >: X](y: Y): Y = x // X<:Y so this would be valid
}

val cMammal:Contra[Mammal] = new Contra(new Mammal)

val a:Animal = cMammal problem new Animal // Animal >: Mammal, this is fine
val m:Mammal = cMammal problem new Mammal // Mammal >: Mammal, this is fine
val d:Mammal = cMammal problem new Dog    // (Dog upcasts to Mammal) >: Mammal, this is fine

val cDog:Contra[Dog] = cMammal // Valid assignment

val a:Animal = cDog problem new Animal // Animal >: Mammal, this is fine
val m:Mammal = cDog problem new Mammal // Mammal >: Mammal, this is fine
val d:Dog    = cDog problem new Dog    // AAAHHHHHHH!!!!!!

This last line would type check, cDog problem new Dog would actually return a Mammal . 这最后一行会输入检查, cDog problem new Dog实际上会返回一个Mammal This is clearly not a good thing. 这显然不是一件好事。 Thankfully the type system doesn't actually let us do this. 值得庆幸的是,类型系统实际上并没有让我们这样做。

QED contravariant type parameter + lower type bound not a good idea to mix. QED逆变型参数+低级类型绑定不是一个好主意混合。

I hope this example helps. 我希望这个例子有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM