Reputation: 521
So what I am trying to do is collect all the Right values from a series of Either results and have all of them available at the end of the chain to do work on them. I also want the chain to fail fast if one of the Either values is a Left.
So after reading around I believe the key to getting this all to work is a combination of a curried function and an applicative functor.
Below is sample code I have so far that is not quite working. Note that I am using monet.js and 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);
});
At the very end I get an object that contains 3 Either values that looks like this:
{ val: { isRightValue: true, value: 'test1' },
val2: { isRightValue: true, value: 'test1' },
val3: { isRightValue: true, value: 'test1' } }
What I want is the 3 actual values. And if you see, one of the Either values is a Left and the chain should have been broken.
I am trying to do this in a pure functional way. That is why I am not mapping and stuffing values in an object out of the scope of the functions.
Any ideas? Alternatives?
Upvotes: 1
Views: 823
Reputation: 521
So I misread the docs: https://monet.github.io/monet.js/#maybe
You need to nest the successive .ap
calls. Below is a reworked example of what I was trying to do above:
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)
});
I am sure there is a elegant way with compose
or some other monad to flatten the chain out, but for the time being I am satisfied.
Upvotes: 1
Reputation: 135247
It looks like you're using .ap
incorrectly
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')
If success
is applied to badegg
for any param, the immediate result will be a Left
. Subsequent calls to .ap
will not affect the 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"
Upvotes: 1