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

时间:2015-01-06 19:28:26

标签: scala

考虑以下内容,编译:

  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))

为什么会出现编译错误(我不理解上面的编译器错误消息),我应该如何解决?

1 个答案:

答案 0 :(得分:3)

这基本上意味着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))