scala专门的通用数值运算

时间:2014-12-06 10:55:11

标签: scala specialized-annotation

我想要一个封装整数和浮点数的类。

基本上我希望能够做到这样的事情

Const(5) + Const(6) = Const(11)
Const(5) + Const(6.0) =  Const(11.0)

包含编译器错误的代码。

case class Const[@specialized(Long,Double) T](value:T){

  def +(that:Const[T]) : Const[T] = {
    Const(this.value + that.value)
  }

}

---- ---错误

:11:错误:类型不匹配;  发现:T  必需:字符串            Const(this.value + that.value)

(不确定为什么它会解析为字符串+运算符)

2 个答案:

答案 0 :(得分:0)

这是一个工作版本(我认为当两个实例按不同类型参数化时,兼容用法需要类型参数):

  case class Const[@specialized(Long, Double) T: scala.Numeric](value:T){

    def +(that:Const[T]) : Const[T] = {

      //Const(implicitly[Numeric[T]].mkNumericOps(this.value) + that.value)
      import Numeric.Implicits._
      Const(this.value + that.value)

    }

  }

用法:Const[Double](2) + Const(3.3)

答案 1 :(得分:0)

您希望能够以与Scala添加不同数字类型相同的方式添加Const类的实例。但Scala不直接添加不同的数字类型,它使用隐式转换来首先使它们成为相同的类型。你也可以这样做。首先,您需要将Numeric添加到您的班级,正如Gábor所说:

case class Const[@specialized(Long, Double) T: Numeric](value: T) {
  import Numeric.Implicits._
  def +(that: Const[T]) = Const(value + that.value)
}

然后,定义隐式转换:

implicit def constConvert[A, B: Numeric](a: Const[A])(implicit conv: A => B) =
  Const[B](a.value)

这接受隐式转换,因此将内置隐式转换推广到您的类型。现在你可以写:

Const(5) + Const(6.0)  // Const(11.0)

编译为:

constConvert(Const(5))(_.toDouble) + Const(6.0)

由于Scala为向上转换数字类型提供了合理的隐式转换,并且constConvert方法接受这种隐式转换,因此这通常适用于内置数字类型,以及定义合理转换和数字的任何新类型。

然而!

你应该知道,你不会真正从这里获得专业化的全部好处,因为标准库Numeric并不是专门的(在撰写本文时),所以仍然会有自动装箱。您可能希望使用Numeric的专用版本,例如Spire提供的版本。