You need to help the compiler a little with expansion to make this work:
q.flatMap(s => tooInt(s))
It all boils down to the fact that we have an implicit option2Iterable
defined in Option.scala
. When you first map
and then flatten
, the Option[Int]
is already in scope and the implicit can be applied. But when you flatMap
, the compiler has to first expand tooInt
to s => tooInt(s)
and then apply the implicit resolution, but that doesn't work. Why doesn't it work? because the compiler looks for an implicit of type:
pt=(=> String => Option[Int]) => (String => scala.collection.GenTraversableOnce[?])
Which doesn't exist. On the contrary, the toInt
method is first expanded into a function type, and then the implicit is searched for Option[Int]
:
-- toInt : pt=String => scala.collection.GenTraversableOnce[?] BYVALmode-EXPRmode-POLYmode (site: value r in X)
| | | | | | |-- { ((s: String) => toInt(s)) } : pt=String => scala.collection.GenTraversableOnce[?] BYVALmode-EXPRmode-POLYmode (site: value r in X)
| | | | | | | |-- ((s: String) => toInt(s)) : pt=String => scala.collection.GenTraversableOnce[?] BYVALmode-EXPRmode-POLYmode (site: value r in X)
| | | | | | | | |-- (s: String)Option[Int] : pt=scala.collection.GenTraversableOnce[?] EXPRmode (site: value $anonfun in X)
| | | | | | | | | |-- s : pt=String BYVALmode-EXPRmode (site: value $anonfun in X)
| | | | | | | | | | \-> String
| | | | | | | | | [search #3] start `(s: String)Option[Int]`, searching for adaptation to pt=Option[Int] => scala.collection.GenTraversableOnce[?] (silent: value $anonfun in X) implicits disabled
| | | | | | | | | [search #3] considering scala.this.Option.option2Iterable
We can also see it in the decompiled code:
val r: scala.collection.immutable.IndexedSeq[Int] = q.flatMap[Int, scala.collection.immutable.IndexedSeq[Int]]({
{
final <artifact> def $anonfun$main(s: String): Iterable[Int] = scala.this.Option.option2Iterable[Int](toInt(s));
((s: String) => $anonfun$main(s))
}
}, immutable.this.IndexedSeq.canBuildFrom[Int]());