问题
Consider the following code, derived from the metascala project:
object Units {
case class Quantity[M <: MInt, T: Numeric](value: T) {
type This = Quantity[M, T]
def *[M2 <: MInt](m: Quantity[M2, T]) =
Quantity[M + M2, T](numeric[T].times(value, m.value))
def /[M2 <: MInt](m: Quantity[M2, T]) =
Quantity[M - M2, T](numeric[T].div(value, m.value))
def apply(v: T) = Quantity[M, T](numeric[T].times(v, value))
}
implicit def measure[T: Numeric](v: T) = Quantity[_0, T](v)
implicit def numericToQuantity[T: Numeric](v: T) =
new QuantityConstructor[T](v)
class QuantityConstructor[T: Numeric](v: T) {
def m = Quantity[_1, T](v)
}
}
(the MInt
is basically the implementation of peano numbers where _0
, _1
are concrete "values" from metascala. Tell me if you need additional code, I just didn't want to paste everything in here.)
I want to support code where some existing Quantity can be multiplied by a simple number, e. g.
import Units._
val length1 = 5 * (5 m) //doesn't work <-----
val length2 = (5 m) * 5 // works
Why is the implicit method measure
not considered in the first line of code as I have assumed?
Instead I get this error message:
overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int cannot be applied to
(scalax.units.Units3.Quantity[scalax.units.Integers._1,Int])
I'm using Scala 2.10-trunk.
This is actually the follow up to How does ‘1 * BigInt(1)’ work and how can I do the same?.
回答1:
To get things started, here's a stand-alone example that gives the same problem,
object Units {
case class Quantity[T: Numeric](value: T) {
def *[M](m: Quantity[T]) = // type M can't be inferred below
Quantity[T](implicitly[Numeric[T]].times(value, m.value))
}
implicit def measure[T: Numeric](v: T) = Quantity[T](v)
val length0 = measure(5) * Quantity(5) // works
val length1 = 5 * Quantity(5) // doesn't work
}
For some reason, the conversion measure
isn't being found because of the type parameter M
on the method *
. If the type parameter is removed from *
, things compile fine. Maybe someone else can explain why?
Edit. This is looking like a limitation of the Scala compiler, since renaming *
to something like ***
resolves the problem. Perhaps the existence of Int.*
(without a type parameter) is precluding the implicit conversion for use of Quantity.*[M]
(with a type parameter). This reminds me of the requirement that overridden methods must have the same exact type parameters.
来源:https://stackoverflow.com/questions/7649517/why-is-the-implicit-conversion-not-considered-in-this-case-with-generic-paramete