Scala: Constraint on generic class type
I am very new to Scala.
I want to implement a generic matrix class "class Matrix[T]". The only constraint on T should be that T should implement a "+" and a "*" mothod/function. How do I go about doing this?
For example I want to be able to use both Int, Double, and my own defined types e.g. Complex
I was thinking something along the lines:
class Matrix[T <: MatrixElement[T]](data: Array[Array[T]]) {
def *(that: Matrix) = ..// code that uses "+" and "*" on the elements
}
abstract class MatrixElement[T] {
def +(that: T): T
def *(that: T): T
}
implicit object DoubleMatrixElement extends MatrixElement[Double]{
def +(that: Double): Double = this + that
def *(that: Double): Double = this * that
}
implicit object ComplexMatrixElement extend开发者_JAVA技巧s MatrixElement[Complex]{
def +(that: Complex): Complex = this + that
def *(that: Complex): Complex = this * that
}
Everything type checks but I still can't instantiate a matrix. Am I missing an implicit constructor? How would I go about making that? Or am I completely wrong about my method?
Thanks in advance Troels
You can use Numeric for Scala 2.8 for that. It is describe here. It would replace MatrixElement and its implementations:
class Matrix[T : Numeric](data: Array[Array[T]]) {
def *(that: Matrix[T]) = //
}
Finally found the answer :-) I think I wasn't that far off in my first try. Here it goes: (written for scala 2.8)
trait MatrixElement[T] {
def +(that: T): T
def *(that: T): T
}
object MatrixElement {
implicit def intToMatrixElement(x : Int) = new MatrixElement[Int] {
def +(y : Int) = x + y
def *(y : Int) = x * y
}
implicit def doubleToMatrixElement(x : Double) = new MatrixElement[Double] {
def +(y : Double) = x + y
def *(y : Double) = x * y
}
implicit def complexToMatrixElement(x : Complex) = new MatrixElement[Complex] {
def +(y : Complex) = x + y
def *(y : Complex) = x * y
}
}
class Matrix[T <% MatrixElement[T] : ClassManifest ](d: Array[Array[T]]) {
def *(that: Matrix) = ..// code that uses "+" and "*" on the elements
}
Now I can do stuff like:
scala> new Matrix(Array(Array(1,0),Array(0,1)))
res0: Matrix[Int] =
1 0
0 1
scala> new Matrix(Array(Array(new Complex(0),new Complex(1)),Array(new Complex(1),new Complex(0))))
res9: Matrix[Complex] =
(0.0,0.0i) (1.0,0.0i)
(1.0,0.0i) (0.0,0.0i)
Here's how the Numeric
solution would look:
// ': Numeric[T]' adds an implicit parameter to the constructor,
// which allows T to be used in arithmetic expressions.
class Matrix[T: Numeric](val data: Array[Array[T]]) {
def *(that: Matrix[T]) = {
val nt = implicitly[Numeric[T]]
import nt._ // This imports an Implicit View to allow operator syntax
this.data(0)(0) * that.data(0)(0)
// etc
}
}
精彩评论