scala - 如何使这个特质协变

标签 scala generics covariance typeclass

我想让以下特征成为协变的,因为知道 DistTraversableLike 在其两个类型参数中都是协变的:

trait TraversableNumOps[T, Repr] extends DistTraversableLike[T, Repr] {

  private def min(a: T, b: T)(implicit num: Numeric[T]) =
    if (num.compare(a, b) <= 0) a else b
  private def max(a: T, b: T)(implicit num: Numeric[T]) =
    if (num.compare(a, b) > 0) a else b

  def maxD(implicit num: Numeric[T]): Option[T] =
    reduceD((a, b) => if (a >= b) a else b)
  def minD(implicit num: Numeric[T]): Option[T] =
    reduceD((a, b) => if (a < b) a else b)
  def sumD(implicit num: Numeric[T]): Option[T] =
    reduceD(_ + _)
  def productD(implicit num: Numeric[T]): Option[T] =
    reduceD(_ * _)

}

但是,我无法在不破坏它的情况下管理它。问题是我想支持 Numeric[T] ,它在 T 中不是协变的。

如何修改此特征,使其在 TRepr 中成为协变?

最佳答案

Repr 应该不是问题,因为它不会显示为任何方法参数的类型。

但是,T 确实出现在逆变位置。 您可以通过在 minmax 上放置 private[this] 修饰符来修改此设置。这将确保这些方法仅在当前对象内使用,并且编译器可以在当前对象的范围内检查差异违规。

对于 maxD 和其他,请考虑让它们采用 T 的父类(super class)型:

def maxD[U >: T](implicit num: Numeric[U]): Option[U]

这解决了方差问题,因为无法使用 T 的父类(super class)型 U 并违反方差(例如,您不能将其分配给对象的字段,因为 TraversableNumOps 不能有 U 类型的字段。

关于scala - 如何使这个特质协变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15635000/

相关文章:

scala - 使用隐式实现 Trait 时避免显式委托(delegate)

swift - 泛型的泛型? A<T<U>> 类?

typescript - Typescript中协变和逆变位置的区别

c++ - C++ 协方差何时是最佳解决方案?

java - 最佳实践 : catching failure points in java.net.URL

python - 控制 Python/Scala 中的表示

scala - Spark- 写入 128 MB 大小的 Parquet 文件

typescript - 使用 typescript 强制执行参数组合

ios - Swift 协变泛型

inheritance - 父类(super class)可以返回子类吗?例如 Marry 函数?