通过组合部分应用的chain实现扁平单子链式调用:chainAp组合子是否有命名?
单子组合子的扁平化尝试
以下是用于创建正确词法作用域的常规嵌套代码:
const chain = xs => fm => function go(i) { if (i === xs.length) return [] else return fm(xs[i]).concat(go(i + 1)); } (0); const of = x => [x]; const bar = xs => chain(xs); const baz = ys => chain(ys); const f = x => y => [x + y]; bar([1,2]) (x => baz([3,4]) (y => f(x) (y))); // [4,5,5,6]
在没有do符号或多触发生成器模拟的情况下,没有语法糖可以扁平化该语法。我们尝试用Kleisli组合以编程方式实现:
const chain = xs => fm => function go(i) { if (i === xs.length) return [] else return fm(xs[i]).concat(go(i + 1)); } (0); const of = x => [x]; const bar = xs => chain(xs); const baz = ys => chain(ys); const f = x => y => [x + y]; const komp = ({chain}) => fm => gm => x => chain(fm(x)) (gm); try {komp({chain}) (bar([1,2])) (baz([3,4])) (f)} catch(e) {console.log(e.message)} console.log( komp({chain}) (bar([1,2])) (baz([3,4])) (x => [y => [x + y]]));
这种方式仅在单子结构嵌套于动作f内时生效,问题只是转移到了单子延续中。
那能否让这个过程隐式进行呢?
const chain = xs => fm => function go(i) { if (i === xs.length) return [] else return fm(xs[i]).concat(go(i + 1)); } (0); const of = x => [x]; const bar = xs => chain(xs); const baz = ys => chain(ys); const f = x => y => [x + y]; const komp = ({chain}) => fm => gm => x => chain(fm(x)) (gm); const comp = f => g => x => f(g(x)); const infix = (x, f, y) => f(x) (y); const chainAp = ({chain, of}) => f => g => hm => chain(f(x => of(hm(x)))) (h => g(y => h(y))); console.log( chainAp({chain, of}) (bar([1,2])) (baz([3,4])) (f)); // [4,5,5,6] const g = infix( bar([1,2]), chainAp({chain, of}), baz([3,4])); console.log(g(f)); // [4,5,5,6]
该组合子似乎适用于非确定性场景,但我不确定它是否适用于其他单子上下文。由于额外的单子上下文是最精简的(of),我认为额外的效应应该像幺半群的empty一样是中性的。
我将这个组合子命名为chainAp,因为其机制与applicative类似,请问它是否已有正式名称?
内容的提问来源于stack exchange,提问作者user5536315
相关产品推荐
相关产品推荐

