我创建了一个可以通过任何可以转换为Numeric
的参数化的类class Complex[T <% Numeric[T]] (val real : T, val imag : T) {
//... complex number methods ...
}
然后在代码的其他地方尝试:
var myComplex = new Complex(0, 1)
这会引发编译错误,因为(令人惊讶的是)Int和Numeric [Int]之间或者Int和Integral [Int]之间没有隐式转换。
我错过了什么吗?在某处我没有看到隐式转换吗?
在Numeric.scala中定义了一个名为IntIsIntegral的隐式对象。我尝试使用它来创建自己的隐式转换方法:
def implicit intToNumericInt(val i : Int)(implicit n : IntIsIntegral) = n.fromInt(i)
我很惊讶这是必需的,无论如何,它似乎导致无限递归到.fromInt方法。
我确信我遗漏了一些基本的东西(正如你所知,我是Scala的新手),所以我们会欣赏正确方向的一点。
从示例中可以看出,我正在尝试使用可以接受和使用任何数字类型的复数实现。我希望将此贡献给scalala(线性代数)项目。接下来,我想介绍一个Trait,它描述矩阵中元素的责任(主要是+和*运算符),并将复杂数字的改进支持到矩阵操作库中。
答案 0 :(得分:9)
你错了。正确的用法是这样的:
class Complex[T](val real : T, val imag : T)(implicit num: Numeric[T]) {
import num._ // make implicit conversions available
//... complex number methods ...
}
与Ordered
和Ordering
之间的差异相同。可以将Ordered[T]
实例与T
进行比较,而Ordering[T]
提供一种比较几个T
的方法。
答案 1 :(得分:2)
在Scala 2.8中,它也可以写成
class Complex[T: Numeric] (val real : T, val imag : T) {
def +(that: Complex[T]) = {
val r = implicitly[Numeric[T]].plus(this.real, that.real)
val i = implicitly[Numeric[T]].plus(this.imag, that.imag)
new Complex(r, i)
}
}
这种语法无疑是有点密集的,但它可以更加可读:
class Complex[T: Numeric] (val real : T, val imag : T) {
val num = implicitly[Numeric[T]]
def +(that: Complex[T]) = {
new Complex(num.plus(this.real, that.real), num.plus(this.imag, that.imag))
}
}
声明class C[T: M]( ... ) { val x = implicitly[M[T]]
似乎等同于class C[T]( ... )(implicit x: M[T]) { import x._
,如前面解决方案的评论中所述。它不仅仅是语法糖,因为编译方式有所不同,例如:在第一种情况下,x
是一种方法,在第二种情况下,它是一个字段。