Scala 协方差分配给父类(super class)型

标签 scala covariance contravariance

我正在尝试找出 scala 协变和逆变。可能会混淆两个不同的概念。 处理下面的代码:

sealed trait Algorithm[ +T <: Model, P <: Model, R <: AnyVal] {
  def name: String
  def train(trainingData: DenseMatrix[Double]): T
  def predict(row: DenseVector[R], mlModel : P): R
}

然后我有两种算法类型声明为:

case class LibLinear() extends Algorithm[Active_Linear, Active_Linear, Double] {
  override val name = "libLinear"
  override def train(trainingData: DenseMatrix[Double]): Active_Linear = {
    ........
  }
  override def predict(row: DenseVector[Double], model: Active_Linear): Double = {
    ..........
  }
}


case class SVM() extends Algorithm[Volume_SVM, Volume_SVM, Double] {
  override val name = "libSVM"
  override def train(trainingData: DenseMatrix[Double]): Volume_SVM = {
    ..........
  }
  override def predict(row: DenseVector[Double], model: Volume_SVM): Double = {
    ...........
  }
}

其中Active_LinearVolume_SVM都是Model的子类型。

现在我不能这样做:

val algorithm: Algorithm[Model, Model, Double] =  SVM()

SVMAlgorithm 的子类型,Volume_SVMModel 的子类型。我们用协变逆变符号声明算法

最佳答案

这是因为算法仅在涉及 T 时才是协变的。 PR 定义为不变式;您必须根据需要在每个代码前面添加 +-,然后相应地修改代码。根据您的最终作业,我做了一些假设,这就是我得出的结论:

sealed trait Algorithm[ +T <: Model, +P <: Model, +R <: AnyVal] {
  def name: String
  def train(trainingData: DenseMatrix[Double]): T
  def predict[U >: R, V >: P](row: DenseVector[U], mlModel : V): U
}

case class LibLinear() extends Algorithm[Active_Linear, Active_Linear, Double] {
  override val name = "libLinear"
  override def train(trainingData: DenseMatrix[Double]): Active_Linear = {
    ...
  }

  override def predict[U >: Double, V >: Active_Linear](row: DenseVector[U], model: V): U = {
    ...
  }
}


case class SVM() extends Algorithm[Volume_SVM, Volume_SVM, Double] {
  override val name = "libSVM"
  override def train(trainingData: DenseMatrix[Double]): Volume_SVM = {
      ...
  }
  override def predict[U >: Double, V >: Volume_SVM](row: DenseVector[U], model: V): U = {
      ...
  }
}

你的最后一个作业就可以正常工作了。

关于Scala 协方差分配给父类(super class)型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35201614/

相关文章:

typescript - TypeScript 中的方差、协方差、逆变和协方差的区别

scala - 为什么该类型导致 "Product with Serializable with Animal"而不仅仅是 Animal?

scala - 在 Spark SQL 中将多个小表与一个大表连接起来的最佳方法

python - python 协议(protocol)中的泛型 - 协方差和逆变

C#:覆盖返回类型

c# - 为什么 List<T> 在协变接口(interface) MyInterface<out T> 上无效

c# - 接口(interface)协变逆变: why is this not compiling?

scala - 如何匹配自定义泛型类型?

eclipse - Scala 项目不会在 Eclipse 中自动构建

c# - 继承需要存储子类特定数据的数组的最佳方法是什么?