Javascript 如何实现单子的通用提升功能?

Javascript 如何实现单子的通用提升功能?,javascript,functional-programming,monads,lifting,Javascript,Functional Programming,Monads,Lifting,我有一系列的算术提升函数: const chain=f=>xs=> x.reduce((acc,x)=>acc.concat(f(x)),[]); 常数=x=>[x]; 常数加=(x,y)=>x+y; 常量liftM2=(链,of)=>f=>m1=>m2=> 链(x=>链(y=>f(x,y)))(m2))(m1); console.log(liftM2(链,of)(添加)([2])([3]));//[5] 是的,您可以在ms上递归执行,但我想折叠更合适: const lift = (chain

我有一系列的算术提升函数:

const chain=f=>xs=>
x.reduce((acc,x)=>acc.concat(f(x)),[]);
常数=x=>[x];
常数加=(x,y)=>x+y;
常量liftM2=(链,of)=>f=>m1=>m2=>
链(x=>链(y=>f(x,y)))(m2))(m1);

console.log(liftM2(链,of)(添加)([2])([3]));//[5]
是的,您可以在
ms
上递归执行,但我想折叠更合适:

const lift = (chain, of) => f => (...ms) =>
  ms.reduceRight((acc, m) =>
    (...xs) => chain(x => acc(...xs, x))(m)
  , (...xs) => of(f(...xs))
  )()

这是递归程序,以防您对它感兴趣-

const chain=f=>xs=>
减少
((acc,x)=>acc.concat(f(x))
, []
)
常数=x=>
[x]
常量添加=(x,…xs)=>
x==未定义
? 0
:x+add(…xs)
常量提升=(链,of)=>f=>(…ms)=>
{const loop=(xs,[m,…rest])=>
m==未定义
?of(f(…xs))
:链(x=>loop([…xs,x],rest))(m)
返回回路([],毫秒)
}
常量打印=(…xs)=>
forEach(x=>console.log(JSON.stringify(x)))
打印
(提升)(链条,of)(增补)()
,升降机(链条,of)(添加)([1])
,提升(链条,of)(添加)([1],[2])
,提升(链条,of)(添加)([1]、[2]、[3])
,提升(链条,of)(添加)([1]、[2]、[3]、[4])
)

//[0][1][3][6][10]
这太棒了。我将尝试实现一个咖喱版本。@bob你的意思是当
f
咖喱化时?这可能比最后调用
f
更有效。不,我的意思是
ms
。无论如何,这本质上就是do符号,对吗?我看不出
lift
do
符号之间有任何相似之处。当然,
lift
可以使用
do
表示法而不是
chain
来实现,但就是这样。好吧,我刚刚计算出do表示法是由编译器转换成monad组合的,转换成我们在这里构建的相同计算结构。您的左折叠对任意monad都不起作用,它假定
chain
返回一个iterable。或者事实上,它甚至不适用于数组monad-请尝试使用不完全包含一个元素的值!哦,糟了。谢谢你接电话。如果我以后有时间的话,我会再看一遍。这个练习很好地解释了链式一元计算是如何工作的。接下来,我将研究应用性提升的区别。