gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 03:49:40 25 4
gpt4 key购买 nike

Scala Language Specification (Section 4.5 on Variance Annotations, p. 44)

  • 类型参数的方差位置与方差位置相反
    封闭类型参数子句的。
  • 类型声明或类型参数下界的方差位置
    与类型声明或参数的差异位置相反。

  • 使用上面的第一点,很容易看出(至少在形式上)
    trait Covariant[+A] {
    def problematic[B <: A](x : B)
    }

    产生错误信息
    error: covariant type A occurs in contravariant position in type >: Nothing <: A of type B
    def problematic[B <: A](x : B)

    使用第一点和第二点很容易看出
    trait Contravariant[-A] {
    def problematic[B >: A](x : B)
    }

    产生错误信息
    error: contravariant type A occurs in covariant position in type >: A <: Any of type B
    def problematic[B >: A](x : B)

    正如我所提到的,很容易从形式上看出(即遵循方差注释的规则)为什么会发生这些错误。但是,我无法举出一个例子来说明这些限制的必要性。相比之下,很容易想出一些例子来说明为什么方法参数应该改变方差位置,参见例如 Checking Variance Annotations .

    所以,我的问题如下:假设上面的两段代码是允许的,出现问题的例子是什么?这意味着,我正在寻找示例 similar to this one这说明了如果不使用上述两个规则可能会出现什么问题。我对涉及下限类型的例子特别感兴趣。

    请注意对 Scala type bounds & variance 的回答留下这个特定的问题,而在 The "lower bound" will reverse the variance of a type, but why? 中给出的答案对我来说似乎错了。

    编辑:我认为第一种情况可以按如下方式处理(改编上面引用的例子)。假设,以下是允许的
    trait Queue[+T] {
    def head : T
    def tail : Queue[T]
    def enqueue[U <: T](x : U) : Queue[T]
    }

    那么我们就可以实现
    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)
    }
    }

    并将其用作
    val x : Queue[Any] = new StrangeIntQueue
    x.enqueue("abc")

    这显然很麻烦。但是,我看不出如何适应它以表明“逆变类型参数+下限类型”的组合也有问题?

    最佳答案

    假设我们允许一个类有一个类型参数 [-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!!!!!!

    最后一行将键入检查, cDog problem new Dog实际上会返回 Mammal .这显然不是一件好事。幸运的是,类型系统实际上并没有让我们这样做。

    Q.E.D.逆变类型参数 + 下类型界限不是混合的好主意。

    我希望这个例子有帮助。

    关于scala - 为什么类型下限会改变方差位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23958349/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com