我理解IO单子和List单子相对于Functor的优势,但是,我不理解Option/Maybe单子相对于Functor的优势。
这是简单的语言类型的整合吗?
或
Option/Maybe Monad在具体应用中比Functor有什么优势?
PS.问具体使用中的优点不是基于观点,因为如果有,它可以被指出,而不带主观方面。
附言,附言,这里有些会员很急,反复催促
Option is both a functor and a monad?
应该是答案,或者QA重复,但实际上不是。
我已经知道了一些基本知识,例如
每个单子都是应用函子,每个应用函子都是函子
这是公认的答案,这不是我想问的
这里有一个很好的答案,这是不包括在以前的问答。
每个问题的方面、细节或解决方案都有很大的不同,因此请避免在这里以粗略的方式“捆绑”不同的东西。
1条答案
按热度按时间ogq8wdun1#
让我们来看看类型。
对于一个函子,我们可以将一个普通的函数
a -> b
应用于f a
类型的值,得到一个f b
类型的值。这个函数永远不会对f
部分发生的事情有发言权,只有内部。把函子看作一种盒子一样的东西,fmap
中的函数永远不会看到盒子本身,只有内部。值被取出并放回它开始时所在的盒子中。应用函子的功能稍微强大一些。现在,我们有一个 * also * in a box的函数。因此,在有限的意义上,函数在
f
部分有发言权。函数和输入都有f
部分(它们彼此独立),这些部分组合成结果。单子的功能更强大,函数没有
f
部分,函数取一个值并 * 产生 * 一个新的盒子,而在Applicative
的情况下,函数的盒子和值的盒子是独立的,在Monad
的情况下,函数的盒子可以 * 依赖于 * 输入值。这是什么意思?你让我关注
Maybe
,那么我们来具体讨论一下Maybe
。提醒一下,
Maybe
看起来像这样。Maybe a
是一个可能存在也可能不存在的值,从函子的Angular 来看,我们通常会认为Nothing
是某种形式的失败,而Just a
是a
类型的成功结果。从
fmap
开始,Maybe
的Functor
示例允许我们在Maybe
内部应用一个函数(如果存在的话),该函数对操作的成功或失败没有发言权:一个失败的Maybe
(即一个Nothing
)必须保持失败,一个成功的Maybe
必须保持成功(显然,我们在这里忽略了undefined
和其他指称语义问题;我假设函数失败的 * 唯一 * 方式是使用Nothing
)。现在,
(<*>)
,应用运算符,接受Maybe (a -> b)
和Maybe a
。这两个运算符中的任何一个都可能失败。如果它们中的任何一个失败了,那么结果是Nothing
,并且 * 只有 * 这两个都成功了,我们才能得到Just
作为我们的结果。这允许我们 * 咖喱 * 运算。具体地说,如果我有一个形式为g :: a -> b -> c
的函数,并且我有值ma :: Maybe a
和mb :: Maybe b
,那么我们可能要把g
应用到ma
和mb
上,但是当我们开始这样做的时候,我们有一个问题。现在我们有了一个可能存在也可能不存在的函数,我们不能用
fmap
代替mb
,因为一个不存在的函数(aNothing
)不能作为fmap
的参数。问题是我们有两个 * 独立 * 的Maybe
值(在我们的例子中是ma
和mb
),在某种意义上,它们在争夺控制权。只有当两个都是Just
时,结果才存在。否则,结果应该是Nothing
。这是一种布尔“与”运算,因为如果任何中间体失败,那么整个计算失败。(注:如果您要查找布尔值“or”,其中任何单个成功都可以从先前的失败中恢复,则您要查找Alternative
)所以我们写
或者,使用Haskell为此目的提供的更方便的同义词,
现在,上述情况的关键词是 independent。
ma
和mb
对对方的成功或失败没有发言权。这在许多情况下是好的,因为这样的代码通常可以并行化(有非常高效的命令行参数解析库,它们正好利用了Applicative
的这个属性)。但是,很明显,这并不总是我们所 * 想要的 *。输入
Monad
。在Maybe
单子中,提供的函数 * 根据输入a
生成 * 一个Maybe b
类型的值。a
的Maybe
部分和b
的Maybe
部分不再是独立的:后者可以直接依赖于前者。例如,以
Maybe
为例:平方根函数。我们不能取负数的平方根(假设这里不处理复数),所以我们假设的平方根看起来像现在,假设我们有一个数
r
,但是r
不是一个简单的数,它来自我们之前的计算,我们的计算可能失败了,也许它之前做了一个平方根,或者试图除以零,或者其他的什么,但是它做了一些有可能产生Nothing
的事情,所以r
是Maybe Double
,我们要求它的平方根。显然,如果
r
已经是Nothing
,那么它的平方根就是Nothing
;如果其他的都算不出来,我们就不可能求平方根了,另一方面,如果r
是负数,那么sqrt
就会失败,得到Nothing
,尽管r
本身就是Just
,所以我们真正想要的是而这正是
Maybe
的Monad
示例所做的。整个计算的结果(并且,即它是
Nothing
还是Just
)不仅取决于r
是否是Nothing
,而且取决于r
的实际值。r
的两个不同的Just
值可以产生成功 * 或 * 失败,这取决于sqrt
的操作。单靠Functor
无法做到这一点,甚至用Applicative
也无法做到这一点。它需要一个Monad
。