2017-01-23 3 views
2

Warum wird der Scala-Compiler Sie nicht flatMap eine Set[Set[_ <: SomeType]] lassen, aber lassen Sie flatMap eine Seq[Seq[_ <: SomeType]]? Dieses Verhalten wird im folgenden Scala-REPL-Protokoll demonstriert.Warum können Sie ein Set nicht flatMap, wenn die Elemente nicht markiert sind, aber Sie können ein Seq FlatMap?

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([email protected], [email protected]), Set([email protected], [email protected])) 

scala> x flatMap { el => el } 
res8: scala.collection.immutable.Set[B] = Set([email protected], [email protected], [email protected], [email protected]) 


// 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([email protected], [email protected]), Set([email protected], [email protected])) 

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([email protected], [email protected]), List([email protected], [email protected])) 

// Works with inner of Seq[B] 
scala> x flatMap { el => el } 
res10: Seq[B] = List([email protected], [email protected], [email protected], [email protected]) 

scala> val x: Seq[Seq[_ <: A]] = Seq(Seq(B(), B()), Seq(B(), B())) 
x: Seq[Seq[_ <: A]] = List(List([email protected], [email protected]), List([email protected], [email protected])) 

// Works with inner of Seq[_ <: A] 
scala> x flatMap { el => el } 
res11: Seq[A] = List([email protected], [email protected], [email protected], [email protected]) 


// 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([email protected], [email protected]), Set([email protected], [email protected])) 

scala> x.toSeq flatMap { elem => elem.toSeq } toSet 
res16: scala.collection.immutable.Set[A] = Set([email protected], [email protected], [email protected], [email protected]) 

Antwort

1

Listen sind kovariant, aber Sets sind invariant. Dies bedeutet, dass, obwohl B ein Subtyp von A ist, Set [B] kein Subtyp von Set [A]

ist