scala - Monads - 扁平化的目的
问题描述
所以我一直在阅读有关 scala 中的 Monads 以及与它们的flatMap
功能和for
理解相关的所有语法。直观地说,我理解为什么 Monads 需要使用函数的map
一部分flatMap
,就像通常当我map
在一个包含零个、一个或多个元素的容器上使用一个函数并返回相同的容器但传入的函数应用于容器。Monad 同样是零个、一个或多个元素的容器。
但是,该flatten
部分的目的是flatMap
什么?我无法理解它背后的直觉。对我来说,这似乎是额外的样板文件,需要传递给的所有函数flatMap
围绕它们的返回值创建一个容器/monad,只是为了让该容器立即flatten
被flatMap
. 我想不出一个简单的例子,flatMap
它不能通过简单地替换为map
. 例如:
var monad = Option(5)
var monad2 = None
def flatAdder(i:Int) = Option(i + 1)
def adder(i:Int) = i + 1
// What I see in all the examples
monad.flatMap(flatAdder)
// Option[Int] = Some(6)
monad.flatMap(flatAdder).flatMap(flatAdder)
// Option[Int] = Some(7)
monad2.flatMap(flatAdder)
// Option[Int] = None
monad2.flatMap(flatAdder).flatMap(flatAdder)
// Option[Int] = None
// Isn't this a lot easier?
monad.map(adder)
// Option[Int] = Some(6)
monad.map(adder).map(adder)
// Option[Int] = Some(7)
monad2.map(adder)
// Option[Int] = None
monad2.map(adder).map(adder)
// Option[Int] = None
对我来说,单独使用map
似乎比使用该部分更直观和简单,flatMap
并且该flatten
部分似乎没有增加任何价值。然而,在 Scala 中,重点放在flatMap
而不是map
,以至于它甚至有自己的for
理解语法,所以很明显我一定遗漏了一些东西。我的问题是:在什么情况下,这flatten
部分flatMap
实际上有用?还有什么其他优势flatMap
呢map
?
解决方案
如果正在处理的每个元素都可能导致零个或多个元素怎么办?
List(4, 0, 15).flatMap(n => primeFactors(n))
//List(2, 2, 3, 5)
如果您有一个可能拼写不正确的名字,并且您想要他们的办公室任务(如果他们有的话)怎么办?
def getID(name:String): Option[EmployeeID] = ???
def getOffice(id:EmployeeID): Option[Office] = ???
val office :Option[Office] =
getID(nameAttempt).flatMap(id => getOffice(id))
flatMap()
当你有一个 monad 并且你需要将它的内容提供给一个 monad 生产者时,你会使用它。你想要的结果Monad[X]
不是Monad[Monad[X]]
。
推荐阅读
- ios - Veracode CWE ID 200:将敏感信息暴露给未经授权的行为者
- javascript - 如何在wordPress中使用jquery
- python - Pandas:将每月数据的 1 个数据帧除以每月平均值的第二个数据帧
- excel - 将工作表复制到另一个工作簿的日期问题
- node.js - 我们可以使用烧瓶渲染 .ejs 文件吗?
- terraform - 我收到错误:运行 terraform 计划时出现循环
- amazon-s3 - 使用 Lambda@Edge 和 Amazon CloudFront 为所有路由(错误路由)添加 HTTP 安全标头
- html - 选择图像后从文件输入框提交表单
- java - 如何使用 JPArepository 通过 Join 获取和保存记录?
- c++ - 关于在头文件的命名空间中使用指令