10

我将一些代码从 2.9 转换为 2.10,遇到了意外的编译错误。这是最小的形式:

在 2.9.2 中,这可以正常工作:

scala> List(1).flatMap(n => Set(1).collect { case w => w })
res0: List[Int] = List(1)

在 2.10.0 中,我们得到一个错误:

scala> List(1).flatMap(n => Set(1).collect { case w => w })
<console>:8: error: no type parameters for method flatMap: (f: Int => scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[List[Int],B,That])That exist so that it can be applied to arguments (Int => scala.collection.immutable.Set[_ <: Int])
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : Int => scala.collection.immutable.Set[_ <: Int]
 required: Int => scala.collection.GenTraversableOnce[?B]
              List(1).flatMap(n => Set(1).collect { case w => w })
                      ^
<console>:8: error: type mismatch;
 found   : Int => scala.collection.immutable.Set[_ <: Int]
 required: Int => scala.collection.GenTraversableOnce[B]
              List(1).flatMap(n => Set(1).collect { case w => w })
                                ^
<console>:8: error: Cannot construct a collection of type That with elements of type B based on a collection of type List[Int].
              List(1).flatMap(n => Set(1).collect { case w => w })
                             ^

但如果我明确地将内部结果转换为 aList或明确指定泛型类型,它在 2.10.0 中工作正常flatmap

scala> List(1).flatMap(n => Set(1).collect { case w => w }.toList)
res1: List[Int] = List(1)
scala> List(1).flatMap[Int, List[Int]](n => Set(1).collect { case w => w })
res2: List[Int] = List(1)

有人可以向我解释一下 2.10 的变化是什么导致类型推断在 2.9 中没有在这里失败吗?

编辑:

再深入一点,我们可以看到问题源于 的行为差异collect

在 2.9.2 中:

scala> Set(1).collect { case w => w }
res1: scala.collection.immutable.Set[Int] = Set(1)

在 2.10.0 中:

scala> Set(1).collect { case w => w }
res4: scala.collection.immutable.Set[_ <: Int] = Set(1)

据推测,原因与Set不同,例如List,类型不变的事实有关。但是更完整的解释,尤其是给出这种改变的动机的解释,会很棒。

4

1 回答 1

6

这是一个错误。您也可以通过键入模式来解决它,如

scala> Set(1).collect { case w => w }
res0: scala.collection.immutable.Set[_ <: Int] = Set(1)

scala> Set(1).collect { case w: Int => w }
res1: scala.collection.immutable.Set[Int] = Set(1)
于 2013-01-06T09:57:22.647 回答