这是单子吗?
我试图理解单子的概念,我想知道这个代码是否是这个概念的实现(在JavaScript中)。
我有返回创建包装方法的set方法的新对象的函数M.
var foo = M().set('getX', function() {
return this.x;
}).set('setX', function(x) {
this.x = x;
}).set('addX', function(x) {
this.x += x;
});
然后我可以链接foo的方法
foo.setX(10).addX(20).addX(30).getX()
将返回60
如果我有方法对象并且用这个对象调用M,那也是一样的。
var foo = {
x: 10,
add: function(x) {
this.x += x;
}
};
M(foo).add(10).add(20).add(30).x
将返回70
函数被包装在M对象中,所以这个方法内部的上下文总是那个M对象。
f = M({x: 20}).set('getX', function() {
return this.x;
}).set('addX', function(x) {
this.x += x;
}).addX(10).getX
所以f是用M包装的对象的上下文的函数 - 如果我调用f()
它将返回30。
我的理解是否正确? M是单子吗?
编辑修改后的代码在github上https://github.com/jcubic/monadic
这是一个monoid模式。 每个状态更新操作(如.setX(10)
.addX(20)
等)都是一个转换一个对象的计算。 (要语法有效,你必须把它写的一个参数的函数function(x) {x.addX(20);}
但我认为这是更清楚,如果我使用简写形式)
有两件事使得这是一个monoid。 首先,存在一个标识元素: .addX(0)
对其对象没有任何作用。 其次,任何两个操作可以合并。 例如, .setX(10).addX(20)
也是一个转换一个对象的计算。
这不是一个monad。 您的方法支持的计算仅限于编写和更新this.x
( .getX()
不是monoid的成员,因为你不能在它之后链接任何东西)。 例如,对于monad,您可以让一个操作链中的一个成员执行if-then-else来决定链中的下一个内容。 你的方法不能这样做。
除了突变之外; 根据我的理解,你写的东西比单子或者幺半群更接近于应用函子。
同样,就我的理解而言,幺半群是一个集合(抽象代数意义上的),它是在一个映射单一类型的操作下关闭的。 如果你只实现了add
那么你可能会说你的原型链实现了一个monoid。 但即使如此,你必须自己手动指定一个二进制操作,在每个参数和每个参数之间,如下所示:
M({x:0}).add(1).add(2)...add(100) === 1050; // or _.reduce([1..100],add)
但是由于你已经将不确定数量的函数绑定到类型( M
),它们都知道如何“解开”该类型,应用预期的函数,然后在退出时恢复“包装器”,那么你有一种应用函数。
如果你已经找到某种方式来组合所有在M
运行的函数的范围,那么你将更接近一元实现:
var bigOpFromLittleOps =
M({x:0}) .bind(function(x0){
return Madd(1) .bind(function(x1){
return Madd(2) .bind(function(x2){
...
return Madd(100) .bind(function(x100){
return Mreturn(x100);
}); ... });});})() === 1050; // Overkill
这样的实现是棘手的,但是让你能够将它们切成小块,并且/或者从较小的块构成更大的块。
链接地址: http://www.djcxy.com/p/47677.html上一篇: Is this a monad?
下一篇: Does the chain function in underscore.js create a monad?