Stavo convertendo un codice da 2.9 a 2.10 e ho trovato un errore di compilazione imprevisto. Ecco la forma minima:comportamento flatMap cambiato in 2.10.0
In 2.9.2, questo funziona bene:
scala> List(1).flatMap(n => Set(1).collect { case w => w })
res0: List[Int] = List(1)
In 2.10.0, otteniamo un errore:
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 })
^
Ma funziona bene in 2.10.0 se mi rivolgo in modo esplicito il risultato interno in un List
o specificare i tipi generici di flatmap
esplicitamente:
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)
Qualcuno può spiegarmi quale sia stato il cambiamento a 2.10 che causa l'inferenza di tipo per fallire qui quando non era in 2.9?
EDIT:
Scavando un po 'di più, si può vedere che il problema deriva da una differenza nel comportamento di collect
:
In 2.9.2:
scala> Set(1).collect { case w => w }
res1: scala.collection.immutable.Set[Int] = Set(1)
In 2.10.0:
scala> Set(1).collect { case w => w }
res4: scala.collection.immutable.Set[_ <: Int] = Set(1)
Presumibilmente la ragione ha a che fare con il fatto che lo Set
, a differenza, ad esempio List
, è di tipo invariante. Ma una spiegazione più completa, e soprattutto quella che dà la motivazione per questo cambiamento, sarebbe grandiosa.
Potrebbe essere quello di rendere le collezioni compatibile per la nuova dinamica Valori di valorizzazione - vale a dire le cose che "estendere" Int sarà ora accettata (supponendo che ho correttamente interpretato correttamente la nuova nozione di valori dinamici. – chaotic3quilibrium