monad确实比较难理解,我认真翻了一个星期资料才理解。
讲得比较好的参考资料:
http://josephguan.github.io/2016/06/25/monad-in-scala/
比较形象的、有图的:
http://blog.forec.cn/2017/03/02/translation-adit-faamip/
数学上讲得比较多的:(scala版代码可用)
https://segmentfault.com/a/1190000008000905
参考资料3中的scala版代码:
1 | // 1. 半群: |
附抄scala版的monad(参考资料1):
1 | trait Monad[+T] { |
下面开始是我个人的理解
函数式语言
函数是一等公民。
无函数副作用。
(学校里教的)
函数可以像普通变量一样使用。(比c里的函数指针更进一步)
更函数式一点
尽量无状态,最好都像lambda演算一样,有很深的递归。
用递归代替循环。
Monad就是这个思想的一个具体实现。
代码层面理解
Monad在scala中就是一个有flatmap的容器,可以把函数fmap的输出收集起来打平回原来的Monad类型。
比较好理解的Monad类型是容器类型:List,Option.
形象上理解
Monad形象上理解类似于有管道操作的容器,可以把函数fmap的输出适配回Monad类型,方便投入下一个函数中。
比较严密的定义上理解:
(去掉范畴学的数学术语,简化理解)
Monad是一个我们定义的集合,它上面有零元(如Option中的None\List中的nil),它上面还有一种二元操作op,op(A,B)的结果依然属于Monad(封闭性),并且运算满足结合律(可以随意加括号)。
所以如果有unit函数(生成零元),flatmap函数(把二元操作打平回集合元素类型,满足封闭性),就可以成为一个Monad了。至于结合律,由于函数都满足结合律,因此可以忽略。
总结:
有map函数: Functor、函子
有ap函数(参数为函数的map): Applicative、应用
有flatmap函数: Monad