I can't figure out how the Scala compiler figures out how to use flatMap
with a sequence of Option
s.
If I use a flatMap
on a sequence of sequences:
println(Seq(Seq(1), Seq()).flatMap(a => a)) // List(1)
it will concatenate all nested sequences
The same happens if I use it with a sequence of Option
s:
println(Seq(Some(1), None).flatMap(a => a)) // List(1)
So the flatMap
treats Option
as a collection in this case. The question is why does this work? The flatMap
has the following definition:
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That
Meaning that it expects a function that returns an instance of GenTraversableOnce
, but Option
does not inherit GenTraversableOnce
. It only inherits Product
and Serializable
, and Product
inherits Equals
.
How does Scala compiler can use the flatMap
on the sequence of Option
s in this case?
Option[A]
is a monad, although this is blurred out due to the generic signature on options flatmap. TheflatMap
(otherwise namedbind
) onOption[A]
should really be:def flatMap(f: A => Option[B]): Option[B]
, which is what you see in functional libraries such as scalaz and cats. – Patsypatt