我想定义一个这样的类型类:
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))
然而,问题是,当我这样做时,我得到Traversable[Any]
并且它
很高兴获得Traversable[Int]
代替:
scala> sum(List(1,2,3) :: List(4, 5) :: Nil)
res10: Traversable[Any] = List(1, 2, 3, 4, 5)
更糟糕的是,我无法定义一个隐含的
在为Traversable[Int]
定义一个之后Traversable[_]
,因为那样
这些定义会引起歧义。把我的头发拉出后我
放弃了。
有什么办法可以让这笔钱归来
Traversable[T]
代替Traversable[Any]
?
看看如何在Scala库中的sum()
上定义Seq
,我可以看到它与Numeric
一起使用,它是不变的,但我想要超类型的默认实现并获得结果与输入不同(与折叠操作相同)很不错。
答案 0 :(得分:12)
我知道将类型参数添加到此类型类的唯一方法是使用def
而不是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)