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

Listしかし、明示的に内部の結果を に変換するか、ジェネリック型をflatmap明示的に指定すると、2.10.0 で正常に動作します。

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.9 では失敗しなかったのに、ここで型推論が失敗する原因となった 2.10 への変更が何であったかを誰かが説明できますか?

編集:

もう少し深く掘り下げると、この問題は の動作の違いから生じることがわかります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 に答える