使用带集合和类型边界的 flatMap 编译错误

Compile error using flatMap with Sets and type bounds

考虑以下编译:

  val f: String => Set[Integer] = ???
  val a: Set[String] = ???
  val b = a.flatMap(s => f(s))

现在,如果我将上面的第一行更改如下,代码将不再编译:

  val f: String => Set[_ <: Integer] = ???
  val a: Set[String] = ???
  val b = a.flatMap(s => f(s))

错误如下:

/Foo.scala:31: error: no type parameters for method flatMap: (f: String => scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Set[String],B,That])That exist so that it can be applied to arguments (String => scala.collection.immutable.Set[_ <: Integer])
[ERROR]  --- because ---
[ERROR] argument expression's type is not compatible with formal parameter type;
[ERROR]  found   : String => scala.collection.immutable.Set[_ <: Integer]
[ERROR]  required: String => scala.collection.GenTraversableOnce[?B]
[ERROR]   val b = a.flatMap(s => f(s))
[ERROR]             ^
[ERROR] /Foo.scala:31: error: type mismatch;
[ERROR]  found   : String => scala.collection.immutable.Set[_ <: Integer]
[ERROR]  required: String => scala.collection.GenTraversableOnce[B]
[ERROR]   val b = a.flatMap(s => f(s))
[ERROR]                       ^
[ERROR] /Foo.scala:31: error: Cannot construct a collection of type That with elements of type B based on a collection of type scala.collection.immutable.Set[String]. 
[ERROR]   val b = a.flatMap(s => f(s))

为什么这里会出现编译错误(我不明白上面的编译错误信息),我该如何解决?

这基本上意味着Scala不知道你说的是什么类型。让我们写一些有用的东西:

val b = a.flatMap[Integer, Set[Integer]](s => f(s))

flatMap 有两个类型参数。第二个参数是您将获得的最终类型。也就是说,上面的 b 将是 Set[Integer] 类型。它很可能被声明为 Set[_ <: Integer],但是这可能会与 f 的声明混淆,所以我决定在那个例子中让它有所不同。

first 参数是将进入该集合的元素类型(即,s => f(s) 将生成的元素)。那么让我们回到 f:

val f: String => Set[_ <: Integer] = ???

生成的元素类型是 Integer 的未知子类型——而且,由于未知,Scala 无法弄清楚要使用什么。或者,换句话说,它无法 推断 flatMap.

的类型参数

顺便说一句,如果你想一直保持Set[_ <: Integer],你可以这样做:

val b = a.flatMap[Integer, Set[_ <: Integer]](s => f(s))

甚至,为了混淆一切,

val b = a.flatMap[T forSome { type T <: Integer }, Set[_ <: Integer]](s => f(s))