在@Pointy 的帮助下,实现“提升”变得微不足道:
function unit(value) {
var rv = $.Deferred();
rv.resolveWith(null, [value]);
return rv.promise();
}
function lift(fn) {
return function(x) {
return unit(fn(x));
};
}
lift(alert)("hello");
function bind(fn) {
return function(x) {
return x.done(function(y) { return fn(y); });
}
}
function compose(f, g) { return function(x) { g(f(x)); } };
function twice(x) { return 2 * x; }
var alert2 = compose(bind(lift(twice)), bind(lift(alert)));
alert2(unit(4)); //error at the end because alert doesn't return any values
现在我只需要弄清楚如何实现[a] -> (a -> M<b>) -> M<[b]>
,以及如何称呼它!
编辑,我最终(a -> M<b>) -> ([a] -> M<[b]>)
改为实施,它看起来像这样:
function listBind(fn) {
return function(a) {
var Mb = $.Deferred();
var b = [], pending = a.length;
var callback = function(i,val) {
b[i] = val;
if(--pending == 0) Mb.resolve(b);
};
for(var i = 0, n = a.length; i < n; i++) {
(function(closure) { //ugly, but have to use closure to 'copy' i
fn(a[closure]).done(function(val) { callback(closure, val); })
})(i);
}
return Mb.promise();
};
}
因此,给定一个获取一个延迟项的函数,此函数 listBind 返回一个新函数,该函数接受一个值数组,并使用它们返回延迟项内的另一个值列表。