gpt4 book ai didi

scala - 为什么我们需要 flatMap(通常)?

转载 作者:行者123 更新时间:2023-12-04 02:39:34 28 4
gpt4 key购买 nike

我一直在研究 FP 语言(断断续续),并且使用过 Scala、Haskell、F# 和其他一些语言。我喜欢我所看到的并理解 FP 的一些基本概念(绝对没有范畴论的背景——所以请不要谈论数学)。

所以,给定一个类型 M[A]我们有 map它采用函数 A=>B并返回 M[B] .但我们也有flatMap它采用函数 A=>M[B]并返回 M[B] .我们还有flatten这需要 M[M[A]]并返回 M[A] .

此外,我读过的许多资料都描述了flatMap。如map后跟 flatten .

所以,鉴于 flatMap似乎相当于 flatten compose map ,它的目的是什么?请不要说它是为了支持“理解”,因为这个问题确实不是 Scala 特有的。我不太关心语法糖,而是关心它背后的概念。 Haskell 的绑定(bind)运算符( >>= )也会出现同样的问题。我相信它们都与某些类别理论概念有关,但我不会说那种语言。

我看过 Brian Beckman 的精彩视频 Don't Fear the Monad不止一次,我想我看到了 flatMap是一元组合运算符,但我从未真正看到它以他描述此运算符的方式使用。它执行此功能吗?如果是这样,我如何将该概念映射到 flatMap ?

顺便说一句,我对这个问题写了很长的文章,其中有很多 list 显示了我试图深入了解 flatMap 含义的实验。然后遇到this question这回答了我的一些问题。有时我讨厌 Scala 的隐式。他们真的可以搅浑水。 :)

最佳答案

FlatMap,在其他一些语言中被称为“绑定(bind)”,正如你自己所说的函数组合。

想象一下,你有一些这样的功能:

def foo(x: Int): Option[Int] = Some(x + 2)
def bar(x: Int): Option[Int] = Some(x * 3)

功能很好,调用 foo(3)返回 Some(5) ,并调用 bar(3)返回 Some(9) ,我们都很高兴。

但是现在您遇到了需要您多次执行操作的情况。
foo(3).map(x => foo(x)) // or just foo(3).map(foo) for short

工作完成了,对吧?

除了不是真的。上面表达式的输出是 Some(Some(7)) ,而不是 Some(7) , 如果你现在想在最后链接另一张 map 你不能因为 foobar采取 Int ,而不是 Option[Int] .

输入 flatMap
foo(3).flatMap(foo)

将返回 Some(7) , 和
foo(3).flatMap(foo).flatMap(bar)

返回 Some(15) .

这很棒!使用 flatMap让你链接形状的函数 A => M[B]被遗忘(在前面的例子中 ABInt ,而 MOption )。

从技术上讲; flatMapbind有签名 M[A] => (A => M[B]) => M[B] ,这意味着它们采用“包装”值,例如 Some(3) , Right('foo) , 或 List(1,2,3)并通过一个通常采用未包装值的函数,例如前面提到的 foobar .它首先“解包”该值,然后将其传递给函数。

我已经看到用于此的盒子类比,因此请注意我专业绘制的 MSPaint 插图:
enter image description here

这种展开和重新包装行为意味着,如果我要引入第三个函数,它不会返回 Option[Int]并尝试 flatMap它的顺序,它不会工作,因为 flatMap期望你返回一个单子(monad)(在这种情况下是 Option )
def baz(x: Int): String = x + " is a number"

foo(3).flatMap(foo).flatMap(bar).flatMap(baz) // <<< ERROR

为了解决这个问题,如果你的函数没有返回一个 monad,你只需要使用常规的 map功能
foo(3).flatMap(foo).flatMap(bar).map(baz)

然后返回 Some("15 is a number")

关于scala - 为什么我们需要 flatMap(通常)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34234687/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com