6

我创建了一个可以通过任何可以转换为数字的东西来参数化的类

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(线性代数)项目。接下来,我想介绍一个描述矩阵中元素职责的特征(主要只是 + 和 * 运算符),并将对复数的支持改进到矩阵操作库中。

4

2 回答 2

10

你用错了。正确的用法是这样的:

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,而 anOrdering[T]提供了一种比较两个 的方法T

于 2010-10-27T12:52:26.313 回答
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是一个方法,在第二种情况下它是一个字段。

于 2010-10-27T14:10:41.750 回答