错误:协变类型 A 出现在逆变位置
我试图编写一个不可变的 Matrix[A] 类。我希望该类在 A
上是协变的,但是当我将 +
放在 A
前面时,编译器开始抱怨该类中的某些操作。
以下是我的 Matrix 类的相关子集(实际类比以下子集大 5 倍):
class Matrix[+A] private(val contents: Vector[Vector[A]])(implicit numericEv: Numeric[A])
extends ((Int, Int) => A) with Proxy {
import numericEv._
import Prelude._
// delegate `equals` and `hashCode` implementations to `contents`
override def self = contents
val nRows: Int = contents.length
val nColumns: Int = contents(0).length.ensuring { len =>
contents.forall(_.length == len)
}
def dimensions = (nRows, nColumns)
def isSquare = nRows == nColumns
def hasSameOrderAs[B : Numeric](that: Matrix[B]) = this.dimensions == that.dimensions
def isComformableWith[B : Numeric](that: Matrix[B]) = this.nColumns == that.nRows
private def assertSameOrder[B : Numeric](that: Matrix[B]) {
assert(this.hasSameOrderAs(that), "Matrices differ in dimensions.")
}
private def assertIsSquare() {
assert(this.isSquare, "Not a square matrix.")
}
def zipWith[B : Numeric, C : Numeric](that: Matrix[B])(f: (A, B) => C): Matrix[C] = {
assertSameOrder(that)
val zippedContents = (contents, that.contents).zipped.map((v1, v2) => (v1, v2).zipped.map(f))
Matrix(zippedContents)
}
def map[B : Numeric](f: A => B): Matrix[B] = {
Matrix(contents.map(_.map(f)))
}
def transpose: Matrix[A] = {
assertIsSquare()
Matrix(contents.transpose)
}
def +(that: Matrix[A]): Matrix[A] = this.zipWith(that)(_ + _)
def -(that: Matrix[A]): Matrix[A] = this.zipWith(that)(_ - _)
def *(scalar: A): Matrix[A] = this.map(_ * scalar)
def *(that: Matrix[A]): Matrix[A] = {
assert(this.isComformableWith(that))
Matrix.tabulate(this.nRows, that.nColumns) { (r, c) =>
(this(r), that.transpose(c)).zipped.map(_ * _).sum
}
}
}
object Matrix {
def apply[A : Numeric](rows: Vector[A]*): Matrix[A] = Matrix(Vector(rows: _*))
def apply[A : Numeric](contents: Vector[Vector[A]]): Matrix[A] = new Matrix(contents)
def tabulate[A : Numeric](nRows: Int, nColumns: Int)(f: (Int, Int) => A): Matrix[A] = {
Matrix(Vector.tabulate(nRows, nColumns)(f))
}
}
对于最后四个操作,编译器显示错误“协变类型 A 出现在逆变位置”班级。我无法理解这些错误的原因以及如何消除它。请解释这些错误背后的原因并提出解决方法。谢谢。
I was trying to write an immutable Matrix[A]
class. I want the class to be covariant on A
but when I put +
in front of A
compiler starts complaining about some operations in the class.
Following is a relevant subset of my Matrix
class (The actual class is some 5 times bigger than the following subset):
class Matrix[+A] private(val contents: Vector[Vector[A]])(implicit numericEv: Numeric[A])
extends ((Int, Int) => A) with Proxy {
import numericEv._
import Prelude._
// delegate `equals` and `hashCode` implementations to `contents`
override def self = contents
val nRows: Int = contents.length
val nColumns: Int = contents(0).length.ensuring { len =>
contents.forall(_.length == len)
}
def dimensions = (nRows, nColumns)
def isSquare = nRows == nColumns
def hasSameOrderAs[B : Numeric](that: Matrix[B]) = this.dimensions == that.dimensions
def isComformableWith[B : Numeric](that: Matrix[B]) = this.nColumns == that.nRows
private def assertSameOrder[B : Numeric](that: Matrix[B]) {
assert(this.hasSameOrderAs(that), "Matrices differ in dimensions.")
}
private def assertIsSquare() {
assert(this.isSquare, "Not a square matrix.")
}
def zipWith[B : Numeric, C : Numeric](that: Matrix[B])(f: (A, B) => C): Matrix[C] = {
assertSameOrder(that)
val zippedContents = (contents, that.contents).zipped.map((v1, v2) => (v1, v2).zipped.map(f))
Matrix(zippedContents)
}
def map[B : Numeric](f: A => B): Matrix[B] = {
Matrix(contents.map(_.map(f)))
}
def transpose: Matrix[A] = {
assertIsSquare()
Matrix(contents.transpose)
}
def +(that: Matrix[A]): Matrix[A] = this.zipWith(that)(_ + _)
def -(that: Matrix[A]): Matrix[A] = this.zipWith(that)(_ - _)
def *(scalar: A): Matrix[A] = this.map(_ * scalar)
def *(that: Matrix[A]): Matrix[A] = {
assert(this.isComformableWith(that))
Matrix.tabulate(this.nRows, that.nColumns) { (r, c) =>
(this(r), that.transpose(c)).zipped.map(_ * _).sum
}
}
}
object Matrix {
def apply[A : Numeric](rows: Vector[A]*): Matrix[A] = Matrix(Vector(rows: _*))
def apply[A : Numeric](contents: Vector[Vector[A]]): Matrix[A] = new Matrix(contents)
def tabulate[A : Numeric](nRows: Int, nColumns: Int)(f: (Int, Int) => A): Matrix[A] = {
Matrix(Vector.tabulate(nRows, nColumns)(f))
}
}
Compiler shows the error "Covariant type A occurs in contravariant position" for the last four operations in the class. I am unable to understand the reason for these errors, and how to get rid of it. Please explain the reason behind these errors and suggest a way to work around them. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
出现这些错误的原因是,像您所做的那样声明它不是类型安全的。例如,可以这样做,否则:
请注意,
m + ma
无法工作,因为m.+
需要一个B< 类型的对象/代码>。不过,如果 Scala 允许您按照自己的方式编写,那么这是允许的。
避免这个问题的常见方法是这样编写方法:
The reason for these errors is that it is not type-safe to declare it as you are doing. For instance, it would be possible to do this, otherwise:
Note that
m + ma
could not work, sincem.+
expects an object of typeB
. If Scala allowed you to write it the way you did, though, this would be allowed.The common way to avoid this problem is to write the method like this: