I’am trying to write something like this:
trait Typed[T]
trait Test {
def testMap: Map[Typed[_], Int]
def test = testMap.flatMap {case (typed, size) => Seq.fill(size)(typed)}
}
But I get the following error:
error: no type parameters for method flatMap: (f: ((Typed[_], Int)) => Traversable[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Map[com.quarta.service.querybuilder.Typed[_],Int],B,That])That exist so that it can be applied to arguments (((Typed[_], Int)) => Seq[Typed[_0]] forSome { type _0 })
--- because ---
argument expression's type is not compatible with formal parameter type;
found : ((Typed[_], Int)) => Seq[Typed[_0]] forSome { type _0 }
required: ((Typed[_], Int)) => Traversable[?B]
def test = testMap.flatMap {case (typed, size) => Seq.fill(size)(typed)}
This code works if change testMap type to:
def testMap: Map[Typed[Any], Int]
What is the difference and how I can solve my problem?
If I understood your question correctly, the answer is: You can do it if
Typedis covariant inT, i.e.trait Typed[+T].Example
Note that I’ve made
Typeda class in this example to get nicer output. You can of course stick with atrait.Now, why is covariance needed here?
Covariance basically means that if
A <: BthenX[A] <: X[B]. So if you were declaringtestMapasMap[Typed[Any], Int]whileTypedwere invariant, you were not allowed to pass in e.g. aTyped[Double]for aTyped[Any]even thoughDouble <: Any. Here, the scala compiler seems to be replacing_withAnyin the covariant case (see extempore’s comment for an elaboration on this).For an explanation of the problem regarding the underscore, I’d refer to Luigi’s answer though.