7

我想定义一个这样的类型类:

trait CanFold[-T, R] {
  def sum(acc: R, elem: T): R
  def zero: R
}

implicit object CanFoldInts extends CanFold[Int, Int] {
  def sum(x: Int, y: Int) = x + y
  def zero = 0
}

implicit object CanFoldSeqs extends CanFold[Traversable[_], Traversable[_]] {
  def sum(x: Traversable[_], y: Traversable[_]) = x ++ y
  def zero = Traversable()
}

def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B = 
  list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))

但是,问题是当我这样做时,我得到了 aTraversable[Any]并且得到 a 会很好Traversable[Int]

 scala> sum(List(1,2,3) :: List(4, 5) :: Nil)
 res10: Traversable[Any] = List(1, 2, 3, 4, 5)

更糟糕的是,我不能在定义一个 for Traversable[Int]之后定义一个隐含的 for Traversable[_],因为这样定义会导致歧义。拔掉头发后,我放弃了。

有什么办法可以使总和返回 a Traversable[T]而不是 a Traversable[Any]

查看Scala 库中的sum()定义方式Seq,我可以看到它适用于Numeric,这是不变的,但我希望超类型的默认实现并且结果与输入不同(与折叠操作相同)很好。

4

1 回答 1

12

我知道向此类类型类添加类型参数的唯一方法是使用 adef而不是 a object

implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
  def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
  def zero = Traversable()
}

scala> sum(List(1, 2, 3) :: List(4, 5) :: Nil)
res0: Traversable[Int] = List(1, 2, 3, 4, 5)
于 2012-11-01T12:16:47.810 回答