简体   繁体   中英

scala specialized general numeric operations

I want a class that encapsulates both integral and floating point numbers.

Basically I want to be able to do something like this

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

The code with compiler errors.

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

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

}

----Error---

:11: error: type mismatch; found : T required: String Const(this.value + that.value)

(not sure why it is resolving to the string + operator)

Here is a working version (I think the type parameter is required for compatible usage when the two instances parametrized by different types):

  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)

    }

  }

Usage: Const[Double](2) + Const(3.3)

You want to be able to add instances of your Const class in the same way that Scala can add different numeric types. But Scala doesn't add different numeric types directly, it uses implicit conversions to first make them the same type. You can do this, too. First, you will need to add Numeric to your class, as Gábor notes:

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

Then, define the implicit conversion:

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

This accepts an implicit conversion, and thus generalizes the builtin implicit conversions to your type. Now you can write:

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

which compiles to something like:

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

Since Scala provides sensible implicit conversions for upcasting numeric types, and the constConvert method accepts such an implicit conversion, this will work generally for the builtin numeric types, plus any new types that define sensible conversions and Numerics.

However!

You should be aware that you won't really get the full benefits of specialization here, since the standard library Numeric is not not specialized (at the time of this writing), so there will still be autoboxing. You may instead want to use a specialized version of Numeric like the one provided by Spire .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM