Monad不就是个自函子范畴上的幺半群,这有什么难理解的(A monad is just a monoid in the category of endofunctors) —— Phillip Wadler
自函子(Endofunctor)
什么是自函数(Endofunction) ?identify :: Number -> Number
自函数就是把类型映射到自身类型。那什么是自函子?
f: cube :: Number -> (Number,String)
F: cube :: (Number,String) -> (Number,String)
f -> F
的映射就是自函子。函子有别于函数,函数描述的是类型之间的映射,而函子描述的是范畴之间的映射。那什么是范畴?简单的理解:不同类型的函数组成的集合。那么自函子就是将范畴映射到自身范畴。这里我们找出一个bind 函子
实现f -> F
的映射。f :: Number -> (Number,String) => F :: (Number,String) -> (Number,String)
var bind = function(f) {
return function F(tuple) {
var x = tuple[0],
s = tuple[1],
fx = f(x),
y = fx[0],
t = fx[1];
return [y, s + t];
};
};
幺半群
幺半群是一个带有二元运算 *: M × M → M 的集合 M ,其符合下列公理: 结合律:对任何在 M 内的a、b、c, (ab)c = a(bc) 。 单位元:存在一在 M 内的元素e,使得任一于 M 内的 a 都会符合 ae = ea = a 。
我们来实现自函子上的结合律:
var compose = function(f, g) {
return function(x) {
return f(g(x));
};
};
var cube = function(x) {
return [x * x * x, 'cube was called.'];
};
var sine = function(x) {
return [Math.sin(x), 'sine was called.'];
};
var f = compose(compose(bind(sine), bind(cube)), bind(cube));
f([3, ''])
var f1 = compose(bind(sine), compose(bind(cube), bind(cube)));
f1([3,''])
>>>
[0.956, 'cube was called.cube was called.sine was called.']
[0.956, 'cube was called.cube was called.sine was called.']
这里f和f1
代表的调用顺序说明满足结合律,同时这个二元运算符就是compose
函数。那如何找到这样一个e
,使得a*e=e*a=a
// unit :: Number -> (Number,String)
var unit = function(x) { return [x, ''] };
var f = compose(bind(sine), bind(cube));
compose(f, bind(unit)) = compose(bind(unit), f) = f
这里的e
就是bind(unit)
了。参考链接: