【问题标题】:How to make trait contravariant when its type parameter appears in an invariant position?当类型参数出现在不变位置时,如何使特征逆变?
【发布时间】:2018-05-30 15:29:04
【问题描述】:

我想在其类型参数中使以下 trait 逆变。

trait Preferences[-A] {
  def ordering: Ordering[A]
}

上述解决方案的问题在于,在 Scala 标准库中,Ordering 的类型参数是不变的。这个SO 帖子讨论了为什么会这样。

我已经为我的问题制定了两种解决方案。第一种解决方案是使参数A和上限。

trait Preferences[-A] {
  def ordering[B <: A]: Ordering[B]
}

第二种是使用implicit

trait Preferences[-A] {
  def ordering(implicit ev: B <:< A): Ordering[B]
}

这两个都可以编译,但我不明白其中的取舍。这些方法之一是否更通用?我应该使用第三种方法吗?

【问题讨论】:

    标签: scala contravariance


    【解决方案1】:

    当您尝试解决您遇到的问题(将逆变参数作为方法或函数的返回类型)时,您的第一个解决方案被认为是最佳实践。

    第二种解决方案称为广义类型约束,当您想要推断正确的类型而不让编译器“适应它们”时,它最有用。例如,如果你有

    def foo[A, B <: A](a: A, b: B): Whatever = ???
    

    你试图调用它

    foo(42, "something")
    

    编译器会推断出AAny,因为这样整个事情就适合了;类型B,即String,确实是Any 的子类型。使用 GTC:

    def foo[A, B](a: A, b: B)(implicit ev: B <:< A)
    

    编译器会从你的参数中推断出它们分别为IntString。只有在那之后它才检查 GTC,并且这里不能进行扩展,因为参数类型已经被推断出来。所以编译会失败,因为String不是Int的子类型。

    只要您明确定义您的 A 和 B,并且您总是会(因为没有什么可以推断它们),您的第一个解决方案就可以了。不需要隐式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 2014-09-01
      • 1970-01-01
      • 2012-03-26
      • 2011-09-08
      相关资源
      最近更新 更多