Почему flatMap на Векторе[Option[Int]], результат функции отображения которого не является вектором[Option[Int]], допустим?
Например,
Vector(Some(1), Some(2), Some(3), None).flatMap{
n => n
}
Производит Vector(1, 2, 3)
вместо того, чтобы давать ошибку. Как я уже видел в других языках, flatMap
используется, когда у вас есть функция отображения, которая производит вложенность, поэтому я ожидал бы, что это будет допустимый flatMap
:
Vector(1, 2, 3).flatMap{
eachNum => Vector(eachNum)
}
Моя функция отображения производит Vector
, которая вызвала бы вложенность (т. е. Vector(Vector(1), Vector(2), Vector(3), Vector(4))
), если бы я использовал map
из-за упаковки контейнера. Однако flatMap
удалит эту вложенность и расплющит ее. Это имеет смысл, когда есть гнездование двух одинаковых монад.
Однако я не понимаю, как использование flatMap
с функцией отображения, которая возвращает Option
, делает Vector[Option[Int]]
Vector[Int]
. Происходит ли какая-то трансформация (я никогда не видел этого раньше), может ли кто-то объяснить и, возможно, указать мне на некоторые ресурсы?
Большое спасибо
2 ответа:
Мы можем использовать
reify
, чтобы увидеть, что происходит: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))
Это показывает нам, что он использует option2Iterable преобразование для преобразования
Option
вIterable
, иIterable
является подтипом типаGenTraversableOnce
, который ожидает flatMap.
Функция
f
передается в пределахflatMap
здесь:Vector(Some(1), Some(2), Some(3), None).flatMap{ n => n }
- это функция
A => GenTraversableOnce[B]
, описанная в реализацииflatMap
:def flatMap[B, That](f : scala.Function1[A, GenTraversableOnce[B]]) (implicit bf : CanBuildFrom[Repr, B, That]) : That = ???
Функция, реализованная в вашем примере
n => n
:Где(n: Option[Int]) => n
A
- этоOption[Int]
, аB
- этоInt
.Потому что
CanBuildFrom
определяется какtrait CanBuildFrom[-From, -Elem, +To]
:
From
- этоRepr
, а в данном случаеVector
Elem
isB
soInt
Результат
flatMap
, следовательно,Vector[Int]