自定义类的List.sum

时间:2014-02-14 19:04:08

标签: list scala types sum

我有以下代表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应该扩展某个接口还是应该实现类型类技术?

3 个答案:

答案 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
   }
 }

sumList的完整签名实际上是:

 def sum(implicit num: Numeric[A])

A的位置是List[A]的类型。