2013-01-05 20 views
10

Przekształcałem kod z 2,9 na 2,10 i natrafiłem na nieoczekiwany błąd kompilacji. Oto minimalna forma:Zachowanie flatMap zmieniono w 2.10.0

W pkt 2.9.2, to działa prawidłowo:

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

W 2.10.0, otrzymujemy błąd:

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

Ale to działa dobrze w 2.10.0 jeśli wyraźnie włączyć wynik wewnętrzną w List lub określenie rodzajowe typy flatmap wyraźnie:

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) 

Czy ktoś może mi wyjaśnić, co zmieniło się w wersji 2.10, co powoduje, że wnioskowanie o typie zawodzi tutaj, gdy nie było w 2,9?

EDIT:

Kopiąc głębiej, widzimy, że problem wynika z różnicy w zachowaniu collect:

W 2.9.2:

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

W 2.10.0:

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

Prawdopodobnie powodem jest fakt, że Set, w przeciwieństwie do, na przykład, List, jest niezmiennikiem typu. Ale pełniejsze wyjaśnienie, a zwłaszcza takie, które daje motywację do tej zmiany, byłoby wspaniałe.

+0

Czy to możliwe, aby zbiory kompatybilny dla nowej wartości dynamicznych ulepszania - czyli rzeczy, które „przedłużyć” Int zostanie przyjęta (zakładając, że mam właściwie zinterpretował poprawnie nowe pojęcie wartości dynamicznych. – chaotic3quilibrium

Odpowiedz

6

To jest bug. Można też obejść wpisując wzór, jak w

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) 
Powiązane problemy