Monad 就是自函子范畴上的一个幺半群
但是举了这么些例子,怎么一点也看不出来 monad 与 monoid 的关系呢?倒是很明确 Monad 是个比较特殊的 Functor。
我们需要进一步的抽象才能解释这句话,首先,回顾前面 Monoid 的知识,比如那个 Sum 的 Monoid。
Sum.of(1).append(Sum.of(2)).append(Sum.of(0)) // => Sum.of(3)
这个 Monoid 很明显,它的二元操作是 append ,幺元是 Sum.of(0) ,范畴是 Sum 。 为了更明显我们可以降一个维度(范畴),把 Sum.of(1) 降成 1
(1 + 2 + 0)
但是 Monad 哪来的二元操作啊?一个 flat ,一个 fmap ,都是一元操作啊?
如果我们降一个维度, 到只有数字的维度上,
(1.2).3 = 1.(2.3)
二元操作 + 可以使得这个等式成立。 而幺元 0,又可以使得
0.2 = 2 = 2.0
在二元操作 + 上成立。
所以我们得到的 monoid 为 (数字集合,二元操作 + ,幺元 0)。
同样的,上升到函子的范畴上[fn:3],注意是自函子 范畴 上的幺半群,就代表的是函子范畴而不是函子实例是幺半群,所以以 Maybe 为例,就需要符合:
(Maybe.Maybe).Maybe = Maybe.(Maybe.Maybe)
能找到一个二元操作使得上式成立?而不是:
(Just.of(1).append(Just.of(2))).append(Just.of(3)) = Just.of(1).append(Just.of(2).append(Just.of(3)))
这个二元操作就是我们刚实现的 Just Monad 的 flat。我们很容易可以把 flat 代入到式子变换成以下格式,
flat(flat(Maybe.Maybe).Maybe) = flat(Maybe.flat(Maybe.Maybe))
其中的 . 是两个类型组合在一起。如同函数的组合是 f.g x= f(g(x)) ,在函子范畴上的组合就是 Maybe 类型的值,在一个 Maybe 类型的容器中:
Maybe.Maybe = Maybe[Maybe]
再代入一遍,就非常清晰结合律的等式是成立的了:
flat(flat(Maybe[Maybe])[Maybe]) = flat(Maybe[flat(Maybe[Maybe])])
大声念出来应该就是: flat 一个容器为 flat(Maybe[Maybe]) 类型,其值类型为 Maybe 得到的类型等于, flat 一个 Maybe 类型,其内值类型为 flat(Maybe[Maybe]) 所得到的类型。
听起来比较像绕口令,仔细看看等式就能理解了。另外一个 monoid 的法则是需要有一个幺元,满足:
?.Maybe = Maybe = Maybe.?
我们很容易能猜到把 Maybe 代入就是我的解,因此任何 Maybe 类型都是幺元:
flat(M[M]) = M = flat(M[M])
所以,flat 就像 moniod 里的 append 一样,但是它并不连接值或是容器,而是连接函子组合,让函子在不同范畴间变换
到这里,我可以告诉你现在的 Just 就是 Monad 了, 它是 Functor 的加强,把 fmap 的结果铺平(flat)。同时又是 Applicative 的加强, Applicative 让我们可以用一般函数作用到在容器中的值,而 Monad 让我们可以把一个容器中的值传入一个接收值的函数中,并返回同样的容器
上面的内容前半段能看懂,但从
###同样的,上升到函子的范畴上[fn:3],注意是自函子 范畴 上的幺半群,就代表的是函子范畴而不是函子实例是幺半群,所以以 Maybe 为例,就需要符合:
这段开始就很费解了。还请作者,对上面的文字推理再进行仔细思考,能否有好的表达?
我是几个月后,再来阅读时,还是堵住了。
另外,我觉得不是flat而是flatmap才是monad幺半群上的二元运算符?
拜托解疑