I'm working with fp-ts library. My function runs in parallel 2 other functions (lets call them first and second) that can either fail or succeed. They both return something like TE.TaskEither<Error, User>
So my function calls them pretty straighforward
TE.sequenceArray([first, second])
This function return type is TE.TaskEither<Error, ReadonlyArray<User>>
Now, the behavior is supposed to be like this:
case errors, succeed:
of [err, err], _ -> left(user does not exist)
of _, [el] -> right(el)
of _, _ -> left(internal server error)
Meaning if any of users is found, the function should return ReadonlyArray<User>>
with either 2 or 1 users, and not throw error.
If there are 2 errors thrown meaning no user is found it should also return Error
wrapped in TaskEither
.
Sorry if my explanation is a bit blurry I'm still pretty new to fp-ts so please be kind to me :)
I've tried to use TE.fold and TE.chain but the issue is that I can't find the way to ignore error when one of calls return it
I tried:
F.pipe(
TE.sequenceArray([fist, second]),
TE.chain(successes => {
if (successes.length > 0) {
return TE.right(successes);
} else {
return TE.left(Error());
}
}),
TE.map(results => results.flat()),
);
This solution seems to ignore my if statement
I'm working with fp-ts library. My function runs in parallel 2 other functions (lets call them first and second) that can either fail or succeed. They both return something like TE.TaskEither<Error, User>
So my function calls them pretty straighforward
TE.sequenceArray([first, second])
This function return type is TE.TaskEither<Error, ReadonlyArray<User>>
Now, the behavior is supposed to be like this:
case errors, succeed:
of [err, err], _ -> left(user does not exist)
of _, [el] -> right(el)
of _, _ -> left(internal server error)
Meaning if any of users is found, the function should return ReadonlyArray<User>>
with either 2 or 1 users, and not throw error.
If there are 2 errors thrown meaning no user is found it should also return Error
wrapped in TaskEither
.
Sorry if my explanation is a bit blurry I'm still pretty new to fp-ts so please be kind to me :)
I've tried to use TE.fold and TE.chain but the issue is that I can't find the way to ignore error when one of calls return it
I tried:
F.pipe(
TE.sequenceArray([fist, second]),
TE.chain(successes => {
if (successes.length > 0) {
return TE.right(successes);
} else {
return TE.left(Error());
}
}),
TE.map(results => results.flat()),
);
This solution seems to ignore my if statement
As mentioned in the comments, TE.sequenceArray
is not what you want. You could instead drop down to Task
's sequenceArray
:
import * as E from 'fp-ts/Either'
import * as F from 'fp-ts/function'
import * as O from 'fp-ts/Option'
import * as RA from 'fp-ts/ReadonlyArray'
import * as RNEA from 'fp-ts/ReadonlyNonEmptyArray'
import * as T from 'fp-ts/Task'
import * as TE from 'fp-ts/TaskEither'
class User {}
declare const first: TE.TaskEither<Error, User>
declare const second: TE.TaskEither<Error, User>
const result: TE.TaskEither<
'user does not exist',
RNEA.ReadonlyNonEmptyArray<User>
> = F.pipe(
T.sequenceArray([first, second]),
T.map(RA.filterMap(O.getRight)),
T.map(RNEA.fromReadonlyArray),
T.map(E.fromOption(() => 'user does not exist')),
)
sequenceArray
is the wrong tool for the job. It only returns the array result if all tasks succeeded. You cannot work with that. – Bergi Commented Mar 19 at 0:25