为什么在这种情况下不考虑使用泛型参数的隐式转换?

时间:2011-10-04 14:30:44

标签: scala implicit units-of-measurement

考虑以下代码,源自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)
  }
}

MInt基本上是peano数字的实现,其中_0_1是来自metascala的具体“值”。告诉我你是否需要额外的代码,我只是不想在这里粘贴所有内容。)

我想支持代码,其中一些现有的数量可以乘以一个简单的数字,例如:克。

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。

这实际上是How does ‘1 * BigInt(1)’ work and how can I do the same?的后续行动。

1 个答案:

答案 0 :(得分:4)

为了开始,这是一个给出同样问题的独立示例,

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,未找到转化*。如果从*中删除了type参数,则编译正常。也许别人可以解释为什么?

编辑。这看起来像是Scala编译器的限制,因为将*重命名为***可以解决问题。也许Int.*没有类型参数)的存在排除了使用Quantity.*[M]带有类型参数)的隐式转换。这让我想起了被覆盖的方法必须具有same exact type parameters

的要求