Scala Misunderstanding Type Constructors

I am trying to write a method that takes Map [K, Collection [V]] and converts it to a map with a different collection type for its values. The method accepts a "multimap" and a builder who will create new collections. I use it as follows:

val multimap = new java.util.HashMap[Int, java.util.List[String]] multimap.put(1, Arrays.asList("One")) multimap.put(2, Arrays.asList("Two", "Three")) val mapOfLists: java.util.Map[Int, java.util.Set[String]] = asMap(multimap, Builder.SET) 

Here's what the builder looks like:

 trait Builder[C[_] <: java.util.Collection[_]] { def create[V]: C[V] } object Builder { val SET = new Builder[java.util.Set]() { def create[V]: java.util.Set[V] = new java.util.HashSet[V] } } 

This is where the implementation of asMap () is executed. It works, but I don’t understand - why do I need a type that ends?

 def asMap[K, V, C[_] <: java.util.Collection[_]]( multimap: java.util.Map[K, _ <: java.util.Collection[V]], builder: Builder[C]): java.util.Map[K, C[V]] = { val result = new java.util.HashMap[K, C[V]] val iterator: Iterator[K] = multimap.keySet.iterator while (iterator.hasNext) { val key = iterator.next val collection: C[V] = builder.create[V] collection.asInstanceOf[java.util.Collection[V]].addAll(multimap.get(key)) result.put(key, collection) } result } 

Without a type case, I get this error:

 [ERROR] error: type mismatch; [INFO] found : java.util.Collection[V] [INFO] required: java.util.Collection[_ <: _$2] where type _$2 [INFO] collection.addAll(multimap.get(key)) 
+6
generics types scala
source share
1 answer

You accidentally created existential types instead of type constructors. The valid constructor type is C[X] <: Collection[X| , so you need to change Builder to

 trait Builder[C[X] <: Collection[X]] { def create[V]: C[V] } 

and signature asMap to

 def asMap[K, V, C[X] <: Collection[X]](multimap: Map[K, _ <: Collection[V]], builder: Builder[C]): Map[K, C[V]] 
+8
source share

All Articles