我有以下代码表示GF2字段:
trait GF2 {
def unary_- = this
def + (that: GF2): GF2
def * (that: GF2): GF2
def / (that: GF2) = that match {
case Zero => throw new IllegalArgumentException("Div by 0")
case _ => this
}
}
object Zero extends GF2 {
override def toString = "Zero"
def + (that: GF2) = that
def * (that: GF2) = this
}
object One extends GF2 {
override def toString = "One"
def + (that: GF2) = that match { case One => Zero ; case _ => this }
def * (that: GF2) = that match { case One => this ; case _ => that }
}
现在我想调用这个函数:List(One, One, Zero, One).sum
这样GF2._+
会被调用求和,我该如何完成呢?GF2
应该扩展一些接口还是应该实现类型类技术?
你需要一个隐式的数字[GF2]:
trait GF2IsNumeric extends Numeric[GF2] {
def plus(x: GF2, y: GF2): GF2 = x + y
def minus(x: GF2, y: GF2): GF2 = x + (-y)
def times(x: GF2, y: GF2): GF2 = x * y
def negate(x: GF2): GF2 = -x
def fromInt(x: Int): GF2 = ???
def toInt(x: GF2): Int = ???
def toLong(x: GF2): Long = ???
def toFloat(x: GF2): Float = ???
def toDouble(x: GF2): Double = ???
override def zero = Zero
override def one = One
}
trait GF2Ordering extends scala.math.Ordering[GF2] {
override def compare(a: GF2, b: GF2) = if (a == b) 0 else if (b == One) 1 else -1
}
implicit object GF2IsNumeric extends GF2IsNumeric with GF2Ordering
然后你可以做:
println(List(One, One, Zero, One).sum)
// One
看看sum
的签名:
def sum[B >: A](implicit num: Numeric[B]): B
我正要建议你通过提供类型和 Numeric[GF2]
的隐式值来使GF2
成为Numeric
类型类的成员,但后来我查看了 Numeric
的定义,并意识到它包含大量与您必须实现的总和完全无关的操作。
我不喜欢这样,我认为sum
方法应该需要一些更抽象的类型类(也许是幺半群?
因此,我认为您最好的选择(除非您想实现整个Numeric
实例)是使用 reduce
(仅适用于非空列表)或fold
:
yourList.reduce(_ + _)
yourList.fold(Zero)(_ + _)
为您的特征实现一个版本的Numeric
才能使其正常工作。有关需要创建的完整定义,请参阅此处。
object InScope{
implicit object GF2Numeric extends Numeric[GF2]{
//..your implementation here
}
}
List
上sum
的完整签名实际上是:
def sum(implicit num: Numeric[A])
其中A
是List[A]
的类型。