Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is flatMap on a Vector[Option[Int]] whose mapper function result is not a Vector[Option[Int]] valid?

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

like image 907
Cal Avatar asked Feb 09 '26 17:02

Cal


1 Answers

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.

like image 192
stew Avatar answered Feb 16 '26 05:02

stew



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!