Open boboyada opened 7 years ago
由于篇幅和JS没有类型系统的原因,可能没有介绍范畴论基础是我的失误,如果感兴趣不知道我这篇博客有没有能对理解帮到一些忙 https://blog.oyanglul.us/grokking-monad/
但是这句话的理解应该是 Monad 就是自函子范畴
说明monad是自函子上的东西,所以它还是自函子functor
上的含幺半群
只是在这个范畴上也能找到自函子的自然变换符合二元操作和幺元并且符合monid的法则而已
感觉说的越多,兔子洞会越深,大概的意思理解就好了,其实对用起来没什么太大的帮助
flat是二元是没错的,这不能对应到函数来理解,因为是范畴上的自然变换,flat是自然变换,monad是东西,flat把两个m变换成一个m
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幺半群上的二元运算符? 拜托解疑