I have reached this far:
implicit def collectionExtras[A](xs: Iterable[A]) = new {
def zipWith[B, C, That](ys: Iterable[B])(f: (A, B) => C)(implicit cbf: Ca
You got close enough. Just a minor change in two lines:
implicit def collectionExtras[A, CC[A] <: IterableLike[A, CC[A]]](xs: CC[A]) = new {
def zipWith[B, C, That](ys: Iterable[B])(f: (A, B) => C)(implicit cbf: CanBuildFrom[CC[A], C, That]) = {
val builder = cbf(xs.repr)
val (i, j) = (xs.iterator, ys.iterator)
while(i.hasNext && j.hasNext) {
builder += f(i.next, j.next)
}
builder.result
}
}
First, you need to get the collection type being passed, so I added CC[A]
as a type parameter. Also, that collection needs to be able to "reproduce" itself -- that is guaranteed by the second type parameter of IterableLike
-- so CC[A] <: IterableLike[A, CC[A]]
. Note that this second parameter of IterableLike
is Repr
, precisely the type of xs.repr
.
Naturally, CanBuildFrom
needs to receive CC[A]
instead of Iterable[A]
. And that's all there is to it.
And the result:
scala> Vector(2, 2, 2).zipWith(Vector(4, 4, 4))(_ * _)
res0: scala.collection.immutable.Vector[Int] = Vector(8, 8, 8)