【发布时间】:2019-06-27 00:27:58
【问题描述】:
这是一个避免嵌套模式的协程,例如 (chain(m) (chain(...)) 用于单子计算:
const some = x => none => some => some(x);
const none = none => some => none;
const option = none => some => tx => tx(none) (some);
const id = x => x;
const of = some;
const chain = fm => m => none => some => m(none) (x => fm(x) (none) (some));
const doM = (chain, of) => gf => {
const it = gf();
const loop = ({done, value}) =>
done
? of(value)
: chain(x => loop(it.next(x))) (value);
return loop(it.next());
};
const tx = some(4),
ty = some(5),
tz = none;
const data = doM(chain, of) (function*() {
const x = yield tx,
y = yield ty,
z = yield tz;
return x + y + z;
});
console.log(
option(0) (id) (data)); // 0
但我无法为应用计算实现等效的协程:
const some = x => none => some => some(x);
const none = none => some => none;
const option = none => some => tx => tx(none) (some);
const id = x => x;
const of = some;
const map = f => t => none => some => t(none) (x => some(f(x)));
const ap = tf => t => none => some => tf(none) (f => t(none) (x => some(f(x))));
const doA = (ap, of) => gf => {
const it = gf();
const loop = ({done, value}, initial) =>
done
? value
: ap(of(x => loop(it.next(x)))) (value);
return loop(it.next());
};
const tx = some(4),
ty = some(5),
tz = none;
const data = doA(ap, of) (function*() {
const x = yield tx,
y = yield ty,
z = yield tz;
return x + y + z;
});
console.log(
option(0) (id) (data)); // none => some => ...
这应该有效,但它没有。额外的功能包装从何而来?我想我在这里的递归有点迷失了。
顺便说一句,我知道这仅适用于确定性仿函数/单子。
【问题讨论】:
-
预期的结果是什么?
0? -
@guest271314 是的。在这个人为的例子中,一元计算和应用计算是可以互换的。
-
js:21 Uncaught TypeError: some is not a function; -
为了模仿 Haskell 的
do表示法,您可能希望生成器的返回值是一元类型,而不是用of包装它。 -
在
doA中,loop总是返回一个应用程序,ap将结果包装在some(f(x))中。ap的类型是(M a -> b) -> M a -> M b,但你提升loop的方式会导致(M a -> M b),所以最终结果是M (M b),而不是预期的M b。
标签: javascript functional-programming monads functor applicative