I'm implementing a generic algorithm to return a collection based on two other collections. The problem can be simplified to
def add[Repr <: Traversable[_]](coll1: Repr, coll2: Repr) = coll1 ++ coll2
The problem occurred when I applied the algorithm on a collection A I've defined as
class A[T] extends Iterable[(Int,T)] with IterableLike[(Int,T), A[T]] { ... }
i.e., the type parameter of A is not the same as for the inherited Iterable. Map uses a similar approach.
Example with Map:
scala> val m1 = Map("a" -> 1, "b" -> 1, "c" -> 1)
m1: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1, b -> 1, c -> 1)
scala> val m2 = Map("a" -> 2, "c" -> 1)
m2: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 2, c -> 1)
Applying add with m1 and m2 as parameters results in a List:
scala> add(m1,m2)
res3: Traversable[Any] = List((a,1), (b,1), (c,1), (a,2), (c,1))
...while the wanted result would be similar to using the ++ method directly:
scala> m1 ++ m2
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 2, b -> 1, c -> 1)
This problem does not occur using a collection B defined as:
class B[T] extends Iterable[T] with IterableLike[T, B[T]] { ... }
e.g., Queue is implemented in a similar way.
Example with Queue:
scala> val q1 = Queue(9,2,5)
q1: scala.collection.immutable.Queue[Int] = Queue(9, 2, 5)
scala> val q2 = Queue(7,3,1)
q2: scala.collection.immutable.Queue[Int] = Queue(7, 3, 1)
Applying add on q1 and q2 gives the wanted result:
scala> add(q1,q2)
res4: Traversable[Any] = Queue(9, 2, 5, 7, 3, 1)
Question: Is there a way to implement add, such that the result will be the same as when using the ++ method directly, for all kinds of travesables (including collections implemented similar to Map)? I have been trying to implement an implicit CanBuildFrom in the companion object of class A, with no luck. It seems to me that the problem is with the algorithm, not the collection implementations since it does not work for Map either.