Подтвердить что ты не робот

Поведение flatMap изменилось в 2.10.0

Я конвертировал некоторый код из 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 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?

EDIT:

Копаем немного глубже, мы видим, что проблема возникает из-за различий в поведении 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, инвариант типа. Но более полное объяснение, и особенно то, что дает мотивацию для этого изменения, было бы здорово.

4b9b3361

Ответ 1

Это ошибка . Вы также можете обойти его, набрав шаблон, как в

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)