scala - flatMap 应用于 List[Option[T]] 时的行为

标签 scala functional-programming

让我们看一下这段代码:

scala> val a = List(Some(4), None)
a: List[Option[Int]] = List(Some(4), None)
scala> a.flatMap( e=> e)
List[Int] = List(4)

为什么在 List[Option[T]] 上应用带有函数 { e => e }flatMap 会返回 List[T] 删除了 None 元素?

具体来说,其背后的概念推理是什么——它是基于函数式编程中的某些现有理论吗?这种行为在其他函数式语言中常见吗?

这虽然确实有用,但同时确实感觉有点神奇和任意。

编辑:

感谢您的反馈和答复。 我重写了我的问题,以更加强调问题的概念性质。我更感兴趣的是了解其背后的形式概念,而不是 Scala 特定的实现细节。

最佳答案

让我们首先看一下 Scaladoc for Option 的伴生对象。在那里我们看到了隐式转换:

implicit def option2Iterable[A](xo: Option[A]): Iterable[A]

这意味着任何选项都可以隐式转换为 Iterable,从而生成包含零个或一个元素的集合。如果您有一个需要 Iterable[A]Option[A],编译器将为您添加转换。

在您的示例中:

val a = List(Some(4), None)
a.flatMap(e => e)

我们正在调用List.flatMap,它采用函数A => GenTraversableOnce[B]。在这种情况下,AOption[Int]B 将被推断为 Int,因为通过魔法隐式转换时,e 在该函数中返回时将从 Option[Int] 转换为 Iterable[Int](这是一个GenTraversableOnce 的子类型)。

此时,我们基本上完成了以下操作:

List(List(1), Nil).flatMap(e => e)

或者,使我们的隐式显式化:

List(Option(1), None).flatMap(e => e.toList)

flatMap 然后适用于 Option,就像适用于 Scala 中的任何线性集合一样:采用 A => List[B] 的函数(再次简化)并生成List[B] 的扁平化集合,取消进程中嵌套集合的嵌套。

关于scala - flatMap 应用于 List[Option[T]] 时的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29214127/

相关文章:

java - IntStream 分步迭代

javascript - 是否有任何可能的方法可以一起使用 .reduce()、.map()、.filter() 方法对该数组进行排序?

scala - 如何使用 Monoid Scala?

Scala for 循环。以简洁的方式获取索引

scala - Play Framework 2.3 和 javascript websocket 客户端库

java - 导致 Shuffle 的 Spark 转换是什么?

scala - 有效地搜索序列序列中的单个第一个匹配

functional-programming - Eff monad 要求与 Debug.Trace.Trace 一起排

Scala 的 Java 7 风格自动资源管理

java - XSLT 之于 XML 就像什么之于 CSV?