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))

ただし、問題は、これを行うと が得られることであり、代わりTraversable[Any]に を取得するとよいでしょう。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[_]。定義が曖昧になるからです。髪を引っ張った後、私はあきらめました。

Traversable[T]その合計を a ではなくa に戻す方法はあり Traversable[Any]ますか?

Scala のライブラリでがどのようsum()に定義されているかを見ると、不変である で動作することがわかりますが、スーパータイプのデフォルトの実装が必要であり、結果が入力とは異なる (折り畳み操作と同じ) ことは素晴らしいことです。SeqNumeric

4

1 に答える 1

12

そのような型クラスに型パラメーターを追加する唯一の方法は、 のdef代わりに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 に答える