The assumption for all GenTraversableOnce
descendants is that they contain an arbitrary number of elements. There's too much of the API and the mechanics that assumes or depends on that, such as Builder
and CanBuildFrom
.
On a deeper level, however, it is important to realize that for-comprehensions, and map
/flatMap
, are monadic operations. Monads are not interchangeable -- you cannot pick a a function A => N[B]
and pass it to an M[A]
to get an N[B]
, for any monad M and N, and Option
and collections are different monads.
Through much implicit magic, all of the collections are treated as if they were a single monad, which leads people to assume that all monads should be interchangeable, which is simply not the case.
Then consider a simple case like this:
val x = Option(1)
val y = List('a', 'b', 'c')
val z = for {
a <- x
b <- y
} yield (a, b)
The type of z
cannot be an Option
, since the result has multiple elements. The only way for it to work would be for it to become something like an Iterable
. That might make some sense for Option
, if you think of it as a collection of at most one element, but it would not make sense for things like a State
or Reader
monad.
And speaking of thinking of Option
as a collection of at most one, that is another reason not to do it. An Option
should be thought of as the presence or absence of an element, not as a collection, and the methods available on which help this subtle distinction. Then again, I know of many people who think this argument, at least, is completely bogus, so take it with a grain of salt.