如何使用通用AnyVal编写函数

时间:2012-10-18 19:54:07

标签: scala

我正在尝试编译以下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)

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

雷克斯是对的。由于x:Long表示x.asInstanceOf [Short]无效,因此当T为short时尝试将初始化程序转换为T时,例程失败。是的,这似乎是合法的。谢谢雷克斯!希望你回答而不是评论,所以我可以给你一个+1。

我确实对初始化程序的类型有一些控制权并且所有Byte都是它的逻辑类型但我需要考虑一下以确保这是唯一的问题,因为doMath的实际实现使用参数来获取延迟值类型,带有一组控制输出的选项。但上面是最简单的形式,我认为你的头上钉了一针。谢谢Rex Kerr!

答案 1 :(得分:0)

隐含的对象并不好。

尝试使用案例类

E.G:

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类。

注意我没有我的计算机,所以我无法测试这个,但过去我尝试以这种方式初始化变量时就是这样。