他の2つのコレクションに基づいてコレクションを返す一般的なアルゴリズムを実装しています。問題は次のように簡略化できます
def add[Repr <: Traversable[_]](coll1: Repr, coll2: Repr) = coll1 ++ coll2
この問題は、次のように定義したコレクションAにアルゴリズムを適用したときに発生しました。
class A[T] extends Iterable[(Int,T)] with IterableLike[(Int,T), A[T]] { ... }
つまり、Aのタイプパラメータは、継承されたIterableの場合と同じではありません。マップは同様のアプローチを使用します。
マップの例:
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)
パラメータとしてm1とm2を指定してaddを適用すると、リストが作成されます。
scala> add(m1,m2)
res3: Traversable[Any] = List((a,1), (b,1), (c,1), (a,2), (c,1))
...必要な結果は、++メソッドを直接使用する場合と同様です。
scala> m1 ++ m2
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 2, b -> 1, c -> 1)
この問題は、次のように定義されたコレクションBを使用しても発生しません。
class B[T] extends Iterable[T] with IterableLike[T, B[T]] { ... }
たとえば、キューは同様の方法で実装されます。
キューの例:
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)
q1とq2にaddを適用すると、目的の結果が得られます。
scala> add(q1,q2)
res4: Traversable[Any] = Queue(9, 2, 5, 7, 3, 1)
質問: すべての種類のトラベサブル(Mapと同様に実装されたコレクションを含む)に対して、++メソッドを直接使用した場合と同じ結果になるようにaddを実装する方法はありますか?私はクラスAのコンパニオンオブジェクトに暗黙のCanBuildFromを実装しようとしていましたが、運がありませんでした。Mapでも機能しないため、問題はコレクションの実装ではなく、アルゴリズムにあるように思われます。