Scala协方差分配给超类型
Scala covariance assignment to super type
我正在尝试弄清楚 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_Linear
和 Volume_SVM
都是 Model
的子类型。
现在我不能这样做了:
val algorithm: Algorithm[Model, Model, Double] = SVM()
SVM
是 Algorithm
的子类型,Volume_SVM
是 Model
的子类型。我们用 covariant
和 contravariant
符号声明 Algorithm
。
那是因为算法只有在T
的时候才是协变的。 P
和 R
定义为不变量;您必须根据需要在它们每个之前加上 +
或 -
,然后相应地修改代码。根据您的最终作业,我做了一些假设,这就是我得出的结论:
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 协变和逆变。可能会混淆两个不同的概念。 处理以下代码:
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_Linear
和 Volume_SVM
都是 Model
的子类型。
现在我不能这样做了:
val algorithm: Algorithm[Model, Model, Double] = SVM()
SVM
是 Algorithm
的子类型,Volume_SVM
是 Model
的子类型。我们用 covariant
和 contravariant
符号声明 Algorithm
。
那是因为算法只有在T
的时候才是协变的。 P
和 R
定义为不变量;您必须根据需要在它们每个之前加上 +
或 -
,然后相应地修改代码。根据您的最终作业,我做了一些假设,这就是我得出的结论:
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 = {
...
}
}
你的最后一个作业可以正常工作。