You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过组合部分应用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:31:06