Scala - неявное преобразование Int в Numeric [Int] - PullRequest
5 голосов
/ 27 октября 2010

Я создал класс, который может быть параметризован всем, что может быть преобразовано в Числовое

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].

Я что-то упустил?Есть ли неявное преобразование где-то, чего я не вижу?

Есть неявный объект с именем IntIsIntegral, определенный в Numeric.scala.Я попытался использовать это для создания собственного метода неявного преобразования:

def implicit intToNumericInt(val i : Int)(implicit n : IntIsIntegral) = n.fromInt(i)

Я удивлен, что это необходимо, и, в любом случае, это может привести к бесконечной рекурсии в метод .fromInt.

Я уверен, что мне не хватает чего-то простого (как вы можете сказать, я новичок в Scala), поэтому был бы признателен за точку в правильном направлении.

Как вы можете видеть изНапример, я пытаюсь заставить работать реализацию Complex number, которая может принимать и работать с любым типом Numeric.Я надеюсь внести свой вклад в проект скалала (линейная алгебра).После этого я хочу ввести черту, описывающую обязанности элементов в матрице (в основном только операторы + и *) и модифицировать поддержку комплексных чисел в библиотеке манипулирования матриц.

Ответы [ 2 ]

9 голосов
/ 27 октября 2010

Вы используете это неправильно. Правильное использование выглядит так:

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.

2 голосов
/ 27 октября 2010

В 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 это метод, а во втором случае это поле.

...