使用Scala值类定义新的数字类型

时间:2015-03-10 10:58:48

标签: scala numbers decimal value-class

当我第一次听说价值课时,我想 - 最后!现在我可以定义自己的数字类型sans对象分配!但结果却比我想象的更难。

我想定义我自己的Decimal类型,Dec64http://dec64.com/)或长支持小数,以进行快速货币计算。但是,AnyVal无法扩展Numeric,因为Numeric不是普遍特征。我尝试跟进Double的Scala代码,但它非常复杂,有AnyValCompanionFractionalProxy和许多private[scala]标记代码,非常有用的评论,如< em>不应在用户代码中扩展。

那么,我如何正确定义自己的数值类型,可以与其他Scala数字一起很好地发挥作用呢?

1 个答案:

答案 0 :(得分:2)

Numeric是一个类型类,所以你的类不会扩展它。相反,您将为您的类型创建类型类的实例。在下面的示例中,为简单起见,我使用Int

final class MyNum(val i: Int) extends AnyVal
object MyNum {
  implicit val numeric: Numeric[MyNum] = new Numeric[MyNum] {
    override def plus(x: MyNum, y: MyNum): MyNum = new MyNum(x.i + y.i)
    override def minus(x: MyNum, y: MyNum): MyNum = new MyNum(x.i - y.i)
    override def times(x: MyNum, y: MyNum): MyNum = new MyNum(x.i * y.i)
    override def negate(x: MyNum): MyNum = new MyNum(-x.i)
    override def fromInt(x: Int): MyNum = new MyNum(x)
    override def toInt(x: MyNum): Int = x.i
    override def toLong(x: MyNum): Long = x.i.toLong
    override def toFloat(x: MyNum): Float = x.i.toFloat
    override def toDouble(x: MyNum): Double = x.i.toDouble
    override def compare(x: MyNum, y: MyNum): Int = x.i.compare(y.i)
  }
}

如果您不熟悉类型类,我建议使用Learn You A Haskell For Great Good,尤其是type classes部分。无论如何,这只是一本很好的书,我强烈建议您阅读整篇文章,以充分了解这些想法的来源。