Где неявные преобразования между Numeric и Double определены в Scala 2.9

Я работал над кодом scala, который компилировался нормально, но каким-то образом я нарушил неявные преобразования и не могу понять, что я сделал не так. Сводя это к очень простому случаю, этот код не компилируется, и причина, по-видимому, в том, что я не импортирую неявные преобразования между Double и Numeric[Double]:

import scala.math.Numeric
import scala.math.Numeric._
import scala.math.Numeric.Implicits._
import Ordering.Implicits._

object ImplicitNumericConversions {
  val v: Numeric[Double] = 3.0
}

Я могу исправить это достаточно легко, предоставив свою собственную функцию:

import scala.math.Numeric

object ImplicitNumericConversions {
  def convertDoubleToNumeric(d: Double)(implicit num: Numeric[Double]): Numeric[Double] = num

  val v: Numeric[Double] = convertDoubleToNumeric(3.0)
}

Если я сделаю функцию преобразования неявной, я получу то, что ищу:

import scala.math.Numeric

object ImplicitNumericConversions {

  implicit def convertDoubleToNumeric(d: Double)(implicit num: Numeric[Double]): Numeric[Double] = num

  val v: Numeric[Double] = 3.0
}

... но почему импорт из scala.math.Numeric не делает этого за меня?

Фактическая проблема, над которой я работаю, выглядит так:

class NumericRange[T <% Numeric[T]](val lower: T, val upper: T) { ... }

object NumericRange {

  def apply[T](lower: T, upper: T)(implicit num: Numeric[T]) = {
    import num._
    new NumericRange[T](lower, upper)
  }
}

... где строка, создающая новый NumericRange, не компилируется с этими ошибками:

Multiple markers at this line
    - No implicit view available from T => scala.math.Numeric[T].
    - not enough arguments for constructor NumericRange: (implicit evidence$1: T => scala.math.Numeric[T])org.reductio.rtree.NumericRange[T]. Unspecified value parameter 
     evidence$1.
    - not enough arguments for constructor NumericRange: (implicit evidence$1: T => scala.math.Numeric[T])org.reductio.rtree.NumericRange[T]. Unspecified value parameter 
     evidence$1.
    - No implicit view available from T => scala.math.Numeric[T].

person richj    schedule 02.12.2012    source источник


Ответы (1)


Numeric – это класс типов, что означает, что вы не работаете с экземплярами Numeric[Double] таким образом. , а скорее у вас есть один неявный Numeric[Double] в области видимости, который указывает, как выполнять числовые операции с Double (см. мой ответ здесь для связанного обсуждения Ordering).

Итак, вы ищете неявный Numeric[T], а не T => Numeric[T]. И, к счастью, есть один из тех, Double, так что вы можете просто написать:

class NumericRange[T: Numeric](val lower: T, val upper: T) { ... }

Or:

class NumericRange[T](val lower: T, val upper: T)(implicit
  ev: Numeric[T]
) { ... }

«Контекстная привязка» в первом — это просто синтаксический сахар для неявного аргумента во втором.

person Travis Brown    schedule 02.12.2012
comment
Это решило проблему для NumericRange. Я попытался применить ту же технику к моей реализации OrderedRange. Использование (неявное ev: Ordering[T]) работало точно так же. Я не смог заставить (неявное ev: Ordered[T]) увидеть операторы сравнения, поэтому есть еще одна загадка, которую нужно решить, но я оставлю это для другого вопроса. Удивительный ответ - спасибо. - person richj; 02.12.2012