【问题标题】:Expression of type doesn't conform to Expected type B类型的表达式不符合预期的类型 B
【发布时间】:2017-07-29 09:36:46
【问题描述】:

我有以下代码来理解协变和下限,我故意让代码有编译错误。

getOrElse 起作用,类似于 Option[+T] 的getOrElse 方法。

我会问为什么 getOrElse2getOrElse3 不能更好地理解协变和下限。

编译错误在代码中粘贴为cmets:

class  MyOption[+A](val x: A) {
  def get():A = x

  //similar to Option.getOrElse,which works
  def getOrElse[B>:A ](default: => B): B = {
    if (x != null) x else  default
  }

  //Compiling Error: Expression of type A doesn't conform to Expected type B
  def getOrElse2[B, A<:B ](default: => B): B = {
    if (x != null) x else  default
  }

  //Covariant type A occurs in controvariant position in type A of value B
  def getOrElse3[B <: A](default:=>B): A = {
    if (x != null) x else  default
  }
}

【问题讨论】:

    标签: scala


    【解决方案1】:

    1.getOrElse3[B &lt;: A]: 表示类型B controvariant ABAsubtype/lowerbound,这不是允许协变类型 A,因为协变类型只启用超类型绑定类型A。这也等于:

    //Error:covariant type A occurs in contravariant position in type A of value default
    def getOrElse3(default: A): A = {
      if (x != null) x else default
    }
    

    那么为什么 Option 类型需要 协方差?这是为了将A绑定到超类型A,就像Some(1)可以被接受参数的方法使用:Option[AnyVal]

    2.def getOrElse2[B, A&lt;:B ]: A&lt;:B 表示定义子类型B的新类型A(不是类级别类型A)。并且由于您将类泛型类型 Ax 返回到类型 B,编译器应该抛出 type mismatch 错误。

    【讨论】:

    • 我理解 [B<:a b a>covariant type only enable the super type bound for type A。
    【解决方案2】:

    通过为方法getOrElse2 指定[A &lt;: B],您定义了一个与x 所属的原始类型A 无关的新本地类型A,如@chengpohi 的回答中所述。

    至于方法getOrElse3[B &lt;: A] 违背了trait Function1 要求其参数是逆变的定义:

    trait Function1[-T1, +R] extends AnyRef {
      abstract def apply(v1: T1): R
      // ...
    }
    

    使用协变[+A],对于A 的子类型S,MyOption[S](x: S) 的实例可以替换MyOption[A](x: A) 的实例;但由于Function1 参数的逆变要求,getOrElse3[S] 不能替换 getOrElse3[A]。出于同样的原因,以下方法也会导致编译器失败:

    // Compiling Error: covariant type A occurs in contravariant position in type A of value default
    def printDefault(default: A): Unit = {
      println(default)
    }
    

    为了保留您的协变 [+A],像在您的第一个 getOrElse 方法中一样将 A 设为下限可以避免 Function1 参数的逆变冲突。

    【讨论】:

    • 我不明白With the covariant [+A], a subtype B of A can replace A, thus violating Function1 argument's contravariance requirement的说法。我现在正在烧脑。
    • @Tom,抱歉我不清楚。我已经完善了相关声明。
    • 感谢@leo-c,我可以理解 MyOption[S](x: S) 可以替换 MyOption[A](x: A) 的一个实例,这是协方差;另外,我理解,getOrElse3[S] 不能代替 getOrElse3[A](getOrElse3[A] 应该可以代替 getOrElse3[S])因为 Fucntion1 的论点是协方差。鉴于这两个事实,我仍然不明白问题出在哪里我的 getOrElse3 方法的谎言,也许我需要一些代码来帮助说明问题(例如,首先假设它的定义是正确的)
    • 你可能想看看class Box[+A] { def set(x: A) : Box[A] = ... }这个blog的例子。
    • 谢谢@leo-c。我创建了一个新问题stackoverflow.com/questions/45434571/…。你能帮忙看看吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 2019-06-10
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    相关资源
    最近更新 更多