Why does "flatMap" work with sequences of Option type in Scala?

Viewed 655

I can't figure out how the Scala compiler figures out how to use flatMap with a sequence of Options.

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 Options:

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 Options in this case?

1 Answers

Your observation is right. In this case, if the compiler can't match the type, it looks for an implicit conversion and finds one in Option's companion object:

import scala.language.implicitConversions

/** 
    An implicit conversion that converts an option to an iterable value
*/

implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList

This makes it possible to treat Options as Iterables.


Also, your code can be simplified using flatten:

Seq(Some(1), None).flatten
Related