使用 Scala 值 类 定义新的数字类型
Using Scala value classes to define new numeric type
当我第一次听说值 类 时,我想——终于!现在我可以定义我自己的数字类型而无需对象分配!但结果比我想象的要难。
我想定义我自己的小数类型,Dec64
(http://dec64.com/) 或用于快速货币计算的长支持小数。但是,AnyVal
不能扩展 Numeric
,因为 Numeric
不是通用特征。我试图跟进 Double
的 Scala 代码,但它相当复杂,有 AnyValCompanion
、FractionalProxy
和许多 private[scala]
标记的代码,以及非常有用的注释,如 不应在用户代码中扩展。
那么,我该如何正确定义我自己的数值类型,以便与其他 Scala 数字一起使用?
Numeric
是一种类型 class,因此您的 class 不会扩展它。相反,您将为您的类型创建类型 class 的实例。在下面的示例中,为了简单起见,我使用 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)
}
}
如果您不熟悉 class 类型,我会推荐 Learn You A Haskell For Great Good, particularly its section on type classes。无论如何,这只是一本好书,我强烈建议您通读整本书,以充分理解这些想法的来源。
当我第一次听说值 类 时,我想——终于!现在我可以定义我自己的数字类型而无需对象分配!但结果比我想象的要难。
我想定义我自己的小数类型,Dec64
(http://dec64.com/) 或用于快速货币计算的长支持小数。但是,AnyVal
不能扩展 Numeric
,因为 Numeric
不是通用特征。我试图跟进 Double
的 Scala 代码,但它相当复杂,有 AnyValCompanion
、FractionalProxy
和许多 private[scala]
标记的代码,以及非常有用的注释,如 不应在用户代码中扩展。
那么,我该如何正确定义我自己的数值类型,以便与其他 Scala 数字一起使用?
Numeric
是一种类型 class,因此您的 class 不会扩展它。相反,您将为您的类型创建类型 class 的实例。在下面的示例中,为了简单起见,我使用 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)
}
}
如果您不熟悉 class 类型,我会推荐 Learn You A Haskell For Great Good, particularly its section on type classes。无论如何,这只是一本好书,我强烈建议您通读整本书,以充分理解这些想法的来源。