这里要说的是避免了嵌套图案像(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 => ...
这应该工作,但事实并非如此。哪里额外函子包装从何而来?我猜我有点在递归失去了这里。
顺便说一句,我知道,这仅适用于确定性的函子/单子。
我不能够实现对应用性的计算等效协程
是的,因为发电机的功能是一元,而不仅仅是应用性。一个yield
表达的操作数可以依赖于以前的yield
表达式的结果 - 这是一个单子的特性。
哪里额外函子包装从何而来?我想我在这里有点失落。
你正在做ap(of(…))(…)
- 这相当于根据map(…)(…)
到Applicative laws。相比于第一片段的chain
通话,这并不做结果的任何解缠,让你得到一个嵌套maybe
类型(在您的实现,被编码为一个功能)。