Reputation: 5206
I'm trying to add some methods to Traversable
trait by pimping via implicit class
.
But I'm kind of lost with CanBuildFrom
trait. Consider the following:
implicit class TraversableExt[+A, +Repr <: Traversable[A]](traversable: Repr) {
def debug[That](name: String)(implicit bf: CanBuildFrom[Repr, A, That]): That =
traversable.map{ a => println(name + ": " + a); a }(bf)
}
This fails with error:
Error:(21, 59) type mismatch;
found : scala.collection.generic.CanBuildFrom[Repr,A,That]
required: scala.collection.generic.CanBuildFrom[Traversable[A],A,That]
traversable.map{ a => println(name + ": " + a); a }(bf) ^
I'm guessing that since Repr
in CanBuildFrom[-Repr, -Elem, +To]
is contravariant and thus my Repr
which is upper-bound by Traversable[A]
may not work.
But overall, I'm pretty lost. Can anyone help?
Upvotes: 4
Views: 195
Reputation: 5556
You have to use TraversableLike
and higher kinded types to make the type inferencer happy and make it work with CanBuildFrom
:
implicit class TraversableExt[A, C[X] <: TraversableLike[X, C[X]]](traversable: C[A]) {
def debug[That](name: String)(implicit bf: CanBuildFrom[C[A], A, That]): That =
traversable.map{ a => println(name + ": " + a); a }(bf)
}
The compiler is now able to correctly infer the type of your collection C[A]
instead of generically look for a CanBuildFrom[Traversable[A],...]
As a rule of thumb, when you want to return the same collection class as the one passed in, you have to use the *Like
classes
Upvotes: 6