Reputation: 67
I'm learning Scala and in the below code using flatMap (taken from filter with flatmap or collect)
I have
list flatMap {
case st: String => Some(st)
case _ => None
}
It works on List[Any]
and yield List[String]
scala> List(1, "A") flatMap {
| case st: String => Some(st)
| case _ => None
| }
res21: List[String] = List(A)
Now I'm confused about the types
here. As I thought, flatMap
works on some kinds of monad
which works as a transformation from M[M[A]] -> M[A]
.
The code bellow is easy to understand,
def flatten(ls: List[Any]): List[Any] = ls flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}
since both case return a List[Any]
, which is still the same type of ls: List[Any]
.
But why Some[String]
and None
are acceptable in the flatMap
of a List[Any]
?
Besides, it seems like None
is completely ignored rather then treated as a serious value ? I was thinking there maybe some kinds of compacting steps to get rid of such values, like:
[1,2,3].concat([,,2,2])
// => (6) [1, 2, 3, empty × 2, 2]
[1,2,3].concat([,,4]).filter(Boolean)
// => (4) [1,2,3,4]
Can someone explain these? Thanks!!!
Upvotes: 1
Views: 114
Reputation: 170713
As I thought, flatMap works on some kinds of monad which works as a transformation from M[M[A]] -> M[A].
Scala flatMap
is more general (which some people don't like).
If you look at documentation, it's enough for the function passed to List#flatMap
to return GenTraversableOnce[SomeType]
, not List[SomeType]
. And even though Option
doesn't extend GenTraversableOnce
, there is an implicit conversion between them which gets applied here.
Besides, it seems like None is completely ignored rather then treated as a serious value ?
None
corresponds to an empty collection, Some(x)
to a single-element collection. So you have e.g.
Some(1) ++ Some(2) ++ None ++ Some(3) ==
List(1) ++ List(2) ++ List() ++ List(3) ==
List(1,2,3)
Or, in your terms, you don't have [1,2,3,,,4]
(which doesn't make sense), but [[1],[2],[3],[],[],[4]]
.
Upvotes: 4
Reputation: 27356
flatMap
is not restricted to nested collections of the same type. The value returned by the function passed to flatMap
can be any collection type. flatMap
will take each element in that collection and append it to the result collection. Option[T]
works like a collection of 0 or 1 elements, so flatMap
works as it would with a List
, Vector
, Array
or other collections.
However in this specific case you would actually use collect
rather than flatMap
:
list.collect{ case s: String => s }
Upvotes: 1