我有以下代表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
应该扩展某个接口还是应该实现类型类技术?
答案 0 :(得分:4)
你需要一个隐含的数字[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
答案 1 :(得分:2)
查看sum
的签名:
def sum[B >: A](implicit num: Numeric[B]): B
我打算通过提供类型GF2
的隐式值来建议Numeric
成为Numeric[GF2]
类型类的成员,但后来我查看了{{1}的定义并意识到它包含大量与您必须实现的总和完全无关的操作。
我不喜欢这个,我认为Numeric
方法应该需要一些更抽象的类型类(一个幺半群,也许?)。
因此,我认为您的最佳选择(除非您要实现整个sum
实例)是使用Numeric
(仅适用于非空列表)或reduce
:
fold
答案 2 :(得分:1)
您需要为您的特征实施Numeric
版本才能使其正常运行。有关您需要创建的完整定义,请参阅here。
object InScope{
implicit object GF2Numeric extends Numeric[GF2]{
//..your implementation here
}
}
sum
上List
的完整签名实际上是:
def sum(implicit num: Numeric[A])
A
的位置是List[A]
的类型。