所以我要做的是从一系列Either结果中收集所有Right值,并在链的末尾使用它们来完成它们的工作。如果其中一个Either值是Left,我也希望链快速失败。
因此,在阅读之后,我相信让这一切全部发挥作用的关键是一个curried函数和一个applicative functor的组合。
下面是我到目前为止的示例代码,但它并不是很有用。请注意,我使用的是monet.js和lodash:
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个实际值。如果你看到,其中一个Either值是Left,链条应该被打破。
我试图以纯粹的功能方式做到这一点。这就是为什么我没有在函数范围之外的对象中映射和填充值。
有什么想法吗?替代?
答案 0 :(得分:1)
您似乎错误地使用了.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
任何参数,则立即结果为Left
。对.ap
的后续调用不会影响Left
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"
答案 1 :(得分:1)
所以我误读了文档:https://monet.github.io/monet.js/#maybe
您需要嵌套连续的.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)
});
我确信compose
或其他一些monad有一种优雅的方式可以将链条弄平,但暂时我很满意。