2013-01-05 16 views
10

我正在將一些代碼從2.9轉換爲2.10,並遇到意外的編譯錯誤。下面是最小的形式:flatMap行爲在2.10.0更改

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

但它在2.10.0工作正常如果我明確把內部結果爲List或明確指定泛型類型的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是類型不變的事實。但是更完整的解釋,特別是能夠激發這種變化的解釋,將會很棒。

+0

莫非是使集合了新的動態兼容的值提高 - 即事「擴展」詮釋現在將接受(假設我有正常正確解釋新的動態值概念。 – chaotic3quilibrium

回答

6

這是一個bug。您也可以解決它通過輸入模式,如在

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)