问题
For example,
Vector(Some(1), Some(2), Some(3), None).flatMap{
n => n
}
produces a Vector(1, 2, 3)
instead of giving an error. As I have seen in other languages, flatMap
is used when you have a mapper function that produces nesting so I would expect this to be a valid flatMap
:
Vector(1, 2, 3).flatMap{
eachNum => Vector(eachNum)
}
My mapper function produces a Vector
which would cause nesting (i.e. Vector(Vector(1), Vector(2), Vector(3), Vector(4))
) if I used a map
due to the container wrapping. However, flatMap
will remove this nesting and flatten it. This makes sense when there is nesting of two identical monads.
However, I do not understand how using a flatMap
with a mapper function that returns an Option
makes a Vector[Option[Int]]
become a Vector[Int]
. Is there some sort of transformation going on (I have never seen this before), could someone explain and perhaps point me to some resources?
Thank you very much
回答1:
we can use reify
to see what is going on:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> val v = Vector(Some(1), Some(2), Some(3), None)
v: scala.collection.immutable.Vector[Option[Int]] = Vector(Some(1), Some(2), Some(3), None)
scala> reify { v.flatMap(x => x) }
res0: reflect.runtime.universe.Expr[scala.collection.immutable.Vector[Int]] =
Expr[scala.collection.immutable.Vector[Int]]($read.v.flatMap(((x) =>
Option.option2Iterable(x)))(Vector.canBuildFrom))
This is showing us that it is using the option2Iterable conversion to convert the Option
to Iterable
, and Iterable
is a subtype of the GenTraversableOnce
type that flatMap is expecting.
回答2:
The function f
passed within the flatMap
here:
Vector(Some(1), Some(2), Some(3), None).flatMap{
n => n
}
Is a function A => GenTraversableOnce[B]
as described in the flatMap
implementation:
def flatMap[B, That](f : scala.Function1[A, GenTraversableOnce[B]])
(implicit bf : CanBuildFrom[Repr, B, That])
: That = ???
The function implemented in your example n => n
is:
(n: Option[Int]) => n
Where A
is Option[Int]
and B
is Int
.
Because CanBuildFrom
is defined as trait CanBuildFrom[-From, -Elem, +To]
:
From
isRepr
, and in this caseVector
Elem
isB
soInt
The result of flatMap
is therefore Vector[Int]
来源:https://stackoverflow.com/questions/34735364/why-is-flatmap-on-a-vectoroptionint-whose-mapper-function-result-is-not-a-ve