Почему неявное преобразование, не рассматриваемое в этом случае с общими параметрами?
Рассмотрим следующий код, полученный из проекта metascala:
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)
}
}
(MInt
- это в основном реализация чисел peano, где _0
, _1
являются конкретными "значениями" из metascala Скажите, нужен ли вам дополнительный код, я просто не хотел вставлять все здесь.)
Я хочу поддерживать код, где некоторое существующее количество может быть умножено на простое число, e. г.
import Units._
val length1 = 5 * (5 m) //doesn't work <-----
val length2 = (5 m) * 5 // works
Почему неявный метод measure
не рассматривается в первой строке кода, как я предполагал?
Вместо этого я получаю это сообщение об ошибке:
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])
Я использую Scala 2.10-trunk.
На самом деле это соответствует Как работает 1 1 BigInt (1) и как я могу сделать то же самое?
Ответы
Ответ 1
Чтобы все началось, вот отдельный пример, который дает ту же проблему,
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
}
По какой-то причине преобразование measure
не найдено из-за параметра типа M
метода *
. Если параметр типа удален из *
, все компилируется в порядке. Может кто-то еще может объяснить, почему?
Изменить. Это похоже на ограничение компилятора Scala, так как переименование *
на что-то вроде ***
устраняет проблему. Возможно, существование Int.*
(без параметра типа) исключает неявное преобразование для использования Quantity.*[M]
(с параметром типа). Это напоминает мне о том, что переопределенные методы должны иметь те же точные параметры типа.