为什么Scala编译器不会让您flatMap
Set[Set[_ <: SomeType]]
,但会flatMap
Seq[Seq[_ <: SomeType]]
?下面的Scala REPL日志中演示了此行为。
scala> class A
defined class A
scala> case class B extends A
defined class B
// If inner collection is of type Set[B] it works
scala> val x = Set(Set(B(), B()), Set(B(), B()))
x: scala.collection.immutable.Set[scala.collection.immutable.Set[B]] = Set(Set(B@6be2b567, B@169d1f92), Set(B@7fcbc336, B@1fe7fa16))
scala> x flatMap { el => el }
res8: scala.collection.immutable.Set[B] = Set(B@6be2b567, B@169d1f92, B@7fcbc336, B@1fe7fa16)
// If inner collection of type Set[_ <: A] it doesn't work
scala> val x: Set[Set[_ <: A]] = Set(Set(B(), B()), Set(B(), B()))
x: Set[Set[_ <: A]] = Set(Set(B@3751baf6, B@27e656e6), Set(B@3cfab56d, B@6b6fde93))
scala> x flatMap { el => el }
<console>:15: error: no type parameters for method flatMap: (f: Set[_ <: A] => scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Set[Set[_ <: A]],B,That])That exist so that it can be applied to arguments (Set[_ <: A] => scala.collection.immutable.Set[_ <: A])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Set[_ <: A] => scala.collection.immutable.Set[_ <: A]
required: Set[_ <: A] => scala.collection.GenTraversableOnce[?B]
x flatMap { el => el }
^
<console>:15: error: type mismatch;
found : Set[_ <: A] => scala.collection.immutable.Set[_ <: A]
required: Set[_ <: A] => scala.collection.GenTraversableOnce[B]
x flatMap { el => el }
^
// Try the same with Seq
scala> val x = Seq(Seq(B(), B()), Seq(B(), B()))
x: Seq[Seq[B]] = List(List(B@53cba89f, B@66ad7167), List(B@14aa2123, B@7def62d0))
// Works with inner of Seq[B]
scala> x flatMap { el => el }
res10: Seq[B] = List(B@53cba89f, B@66ad7167, B@14aa2123, B@7def62d0)
scala> val x: Seq[Seq[_ <: A]] = Seq(Seq(B(), B()), Seq(B(), B()))
x: Seq[Seq[_ <: A]] = List(List(B@7a9e44ff, B@1f8e1096), List(B@13a35d3b, B@1cd93693))
// Works with inner of Seq[_ <: A]
scala> x flatMap { el => el }
res11: Seq[A] = List(B@7a9e44ff, B@1f8e1096, B@13a35d3b, B@1cd93693)
// If inner collection of type Set[_ <: A] it works if we convert to Seq and back to Set again
scala> val x: Set[Set[_ <: A]] = Set(Set(B(), B()), Set(B(), B()))
x: Set[Set[_ <: A]] = Set(Set(B@3751baf6, B@27e656e6), Set(B@3cfab56d, B@6b6fde93))
scala> x.toSeq flatMap { elem => elem.toSeq } toSet
res16: scala.collection.immutable.Set[A] = Set(B@6ab56a77, B@216a3aba, B@9760f17, B@13cfa1ec)
答案 0 :(得分:1)
列表是协变的,但集合是不变的。这意味着虽然B是A的子类型,但Set [B]不是Set [A]的子类型