That doesn’t look entirely right.
trait Aggregateable[M[_]] {
def foldLeft[A, B](m: M[A])(z: B)(op: (B, A) => B): B
}
We don’t depend on the generic type parameter for M
in the signature, so it can be a val
or, more convenient, an object
:
implicit object ListAggregateable extends Aggregateable[List] {
override def foldLeft[A, B](m: List[A])(z: B)(op: (B, A) => B): B = m.foldLeft(z)(op)
}
However, this way we’d have to implement a type class instance for each concrete collection. I’ve tried to come up with an instance at TraversableOnce
level. (Now requiring a def
, indeed.) It kind of seems to work, but…
implicit def traversableOnceAggregateable[T[a] <: TraversableOnce[a]]: Aggregateable[T] =
new Aggregateable[T] {
override def foldLeft[A, B](m: T[A])(z: B)(op: (B, A) => B): B = m.foldLeft(z)(op)
}
…I have no idea how to interpret/explain the effect of the ‘a
’ type parameter. I can’t use ‘_
’ instead because then T[A]
won’t be accepted as a subtype of TraversableOnce[A]
, and thus op
will be rejected as an argument to #foldLeft()
. Any explanation about what’s going on there (or just the proper term(s) to throw at a web search) would be appreciated.
Exactly. The signature would become
def treeAggregate[M[_] : Aggregateable, A, B](objects: M[A], init: B, seqop: A => B, combop: (B, B) => B): B
…and the #foldLeft()
invocation would be implicitly[Aggregateable[M]].foldLeft(objects)(...)
.