为什么VectorMap [Option [Int]]上的flatMap的mapper函数结果不是Vector [Option [Int]]有效?

时间:2016-01-12 04:02:11

标签: scala functional-programming monads flatmap

例如,

Vector(Some(1), Some(2), Some(3), None).flatMap{
  n => n
}

生成Vector(1, 2, 3)而不是出错。正如我在其他语言中看到的那样,当你有一个生成嵌套的mapper函数时会使用flatMap,所以我希望这是一个有效的flatMap

Vector(1, 2, 3).flatMap{
  eachNum => Vector(eachNum)
}

我的mapper函数产生一个Vector,如果由于容器包装而使用Vector(Vector(1), Vector(2), Vector(3), Vector(4)),则会导致嵌套(即map)。但是,flatMap将删除此嵌套并将其展平。当有两个相同的monad嵌套时,这是有意义的。

但是,我不明白如何使用带有flatMap的映射器函数的Option使Vector[Option[Int]]成为Vector[Int]。是否存在某种转变(我以前从未见过这种转变),有人可以解释并且可能指向我一些资源吗?

非常感谢

2 个答案:

答案 0 :(得分:8)

我们可以使用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是flatMap期待的GenTraversableOnce类型的子类型

答案 1 :(得分:3)

此处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

AOption[Int]BInt

因为CanBuildFrom定义为trait CanBuildFrom[-From, -Elem, +To]

  • FromRepr,在本例中为Vector
  • Elem B Int

flatMap的结果是Vector[Int]