Почему 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]) => nA- этоOption[Int], аB- этоInt.Потому что
CanBuildFromопределяется какtrait CanBuildFrom[-From, -Elem, +To]:
From- этоRepr, а в данном случаеVectorElemisBsoIntРезультат
flatMap, следовательно,Vector[Int]