richj
richj

Reputation: 7529

Where are the implicit conversions between Numeric and Double defined in Scala 2.9

I've been working on some scala code that was compiling fine, but somehow I've broken the implicit conversions and I can't work out what I've done wrong. Boiling it down to a very simple case, this code doesn't compile and the reason seems to be that I'm not importing the implicit conversions between Double and 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
}

I can fix this easily enough by providing my own function:

import scala.math.Numeric

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

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

If I make the conversion function implicit then I get what I'm looking for:

import scala.math.Numeric

object ImplicitNumericConversions {

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

  val v: Numeric[Double] = 3.0
}

... but why don't the imports from scala.math.Numeric do this for me?

The actual problem that I'm working on looks like this:

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)
  }
}

... where the line creating the new NumericRange does not compile with these errors:

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

Upvotes: 3

Views: 1658

Answers (1)

Travis Brown
Travis Brown

Reputation: 139058

Numeric is a type class, which means you don't work with instances of Numeric[Double] in this way, but rather that you have a single implicit Numeric[Double] in scope that specifies how to perform numeric operations on Double (see my answer here for a related discussion of Ordering).

So you're looking for an implicit Numeric[T], not a T => Numeric[T]. And fortunately there is one of those in scope for Double, so you can just write:

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

Or:

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

The "context bound" in the first is just syntactic sugar for the implicit argument in the second.

Upvotes: 5

Related Questions