问题
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].
回答1:
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.
来源:https://stackoverflow.com/questions/13670636/where-are-the-implicit-conversions-between-numeric-and-double-defined-in-scala-2