Functional programming 或者Monad:如何收集所有正确的值,并在最后处理所有这些值?
所以我要做的是从一系列的结果中收集所有正确的值,并在链的末端将它们全部用于处理它们。如果其中一个值是左,我还希望链快速失效 因此,在阅读了相关内容后,我认为实现这一切的关键是将curried函数和applicative functor结合起来 下面是我到目前为止还没有完全工作的示例代码。请注意,我使用的是monet.js和lodash:Functional programming 或者Monad:如何收集所有正确的值,并在最后处理所有这些值?,functional-programming,monads,either,monetjs,Functional Programming,Monads,Either,Monetjs,所以我要做的是从一系列的结果中收集所有正确的值,并在链的末端将它们全部用于处理它们。如果其中一个值是左,我还希望链快速失效 因此,在阅读了相关内容后,我认为实现这一切的关键是将curried函数和applicative functor结合起来 下面是我到目前为止还没有完全工作的示例代码。请注意,我使用的是monet.js和lodash: const test1 = Right('test1'); const test2 = Left('test2'); const test3 = Right('
const test1 = Right('test1');
const test2 = Left('test2');
const test3 = Right('test3');
function success(val, val2, val3){
return {
val, val2, val3
};
}
const curriedFn = _.curry(success);
Right(curriedFn)
.ap(Right(function(fn){
return fn(test1);
}))
.ap(Right(function(fn){
return fn(test1);
}))
.ap(Right(function(fn){
return fn(test1);
}))
.map(function(res){
console.log(res);
});
最后,我得到一个包含3个值的对象,如下所示:
{ val: { isRightValue: true, value: 'test1' },
val2: { isRightValue: true, value: 'test1' },
val3: { isRightValue: true, value: 'test1' } }
我想要的是3个实际值。若你们看到了,其中一个值是一个左,这个链应该已经断了
我试图以一种纯粹的功能性方式来做这件事。这就是为什么我不将值映射和填充到函数范围之外的对象中
有什么想法吗?备选方案?看起来您使用的
.ap
不正确
const Either =
require ('data.either')
const { Left, Right } =
Either
const success = x => y => z =>
[ x, y, z ]
const a =
Right (1)
const b =
Right (2)
const c =
Right (3)
const badegg =
Left ('badegg')
如果对任何参数的success
应用于badegg
,则立即的结果将是左
。对.ap
的后续调用不会影响左侧的
Right (success)
.ap (a)
.ap (b)
.ap (c)
.fold (console.error, console.log) // [ 1, 2, 3 ]
Right (success)
.ap (badegg)
.ap (b)
.ap (c)
.fold (console.error, console.log) // "badegg"
Right (success)
.ap (a)
.ap (badegg)
.ap (c)
.fold (console.error, console.log) // "badegg"
Right (success)
.ap (a)
.ap (b)
.ap (badegg)
.fold (console.error, console.log) // "badegg"
所以我误读了文件:
您需要嵌套连续的.ap
调用。下面是我试图在上面做的修改示例:
const test1 = Right('test1');
const test2 = Right('test2');
const test3 = Right('test3');
const success = _.curry(function (val, val2, val3){
return {
val,
val2,
val3
};
});
test3.ap(test2.ap(test1.map(success)))
.map(success => {
console.log(success)
});
我相信有一种优雅的方法可以用组合
或其他单子来拉平链条,但目前我很满意