0

我正在尝试编译以下 Scala 代码:

// Something that Scala is very bad at: don't try and figure out if every type I *could* possibly use supports it,
// just let me use it until I try a type that doesn't.  Or at least have AnyValue provide an abstraction for all
// Numeric Types (Interface)
trait NumericValue[T] {
  def +(rhs : T, lhs : T) : T
}
implicit object ByteNumericValue extends NumericValue[Byte] {
  def +(rhs : Byte, lhs : Byte) : Byte = (rhs + lhs).toByte
}
implicit object ShortNumericValue extends NumericValue[Short] {
  def +(rhs : Short, lhs : Short) : Short = (rhs + lhs).toShort
}
implicit object IntNumericValue extends NumericValue[Int] {
  def +(rhs : Int, lhs : Int) : Int = rhs + lhs
}
implicit object LongNumericValue extends NumericValue[Long] {
  def +(rhs : Long, lhs : Long) : Long = rhs + lhs
}
implicit object BigIntNumericValue extends NumericValue[BigInt] {
  def +(rhs : BigInt, lhs : BigInt) : BigInt = rhs + lhs
}

def doMath[T <: AnyVal](initializer : Long)(implicit Num : NumericValue[T]) : T = {
  Num.+(initializer.asInstanceOf[T], initializer.asInstanceOf[T])
}

lazy val math = doMath[Short](0)

这里的想法是我需要一种方法来使 doMath 对任何 Integer 进行操作,从而对具有加法运算符的类型进行操作。我希望它与 BigInt 之类的大数字或 Byte 之类的非常小的数字无关。

当我尝试编译它时,我得到一个错误:

error: could not find implicit value for parameter Num: NumericValue[Short]
lazy val math = doMath[Short](0)

有任何想法吗?

4

2 回答 2

0

隐式对象不好。

尝试使用案例类

例如:

case class LongNumericValue(l: Long) extends NumericValue[Long] {
  def +(l2 : Long) : Long = l + l2
}

def doMath[T <: AnyVal](implicit Num : NumericValue[T]) : T = {
  Num + Num
}

我将解释:在上面的示例中,doMath 采用 NumericValue[T] 类型的单个值(即 NumericValue[Long]),但如果接收到的值是 Long 类型,编译器将为其查找隐含值,即 case 类。

注意我没有我的电脑,所以我无法测试这个,但过去当我尝试以这种方式初始化变量时它确实如此。

于 2012-10-19T00:02:12.533 回答
0

雷克斯是对的。由于 x : Long 意味着 x.asInstanceOf[Short] 无效,因此当 T 很短时尝试将初始化程序强制转换为 T 时,例程会失败。是的,这似乎是合法的。谢谢雷克斯!希望您回答而不是发表评论,以便我可以给您 +1。

我确实对初始化程序的类型有一些控制,并且所有 Byte 都是它的逻辑类型,但我需要考虑一下以确保这是唯一的问题,因为 doMath 的实际实现使用参数来获取惰性值类型有一堆控制输出的选项。但以上是最简单的形式,我认为你一针见血。谢谢雷克斯科尔!

于 2012-10-18T21:12:57.437 回答