Open flakey-bit opened 2 years ago
Yes, sequenceAcc
is meant to transform a list of either values into an either of a list.
and liftApAcc
is meant to enable to take a function that doesn't operate on Either values, and "lift" it so it can operate on either values.
So none of them enables exactly what you want.
However I feel that flatMap for a validation/either accumulation purpose is a bit artificial, because the point is that you're supposed to transform the value, meaning often change the type of the value you work on.
so, if i have: fnA: T -> Either<Error, U> fnB: U -> Either<Error, V>
first you call fnA, and it returns Left
If I look at the implementation of Validation.flatMap from the vavr java library, the contents support this:
@SuppressWarnings("unchecked")
public final <U> Validation<E, U> flatMap(Function<? super T, ? extends Validation<E, ? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return isInvalid() ? (Validation<E, U>) this : (Validation<E, U>) mapper.apply(get());
}
in case the validation is invalid, it returns this
and casts it as the other type..
So I feel flatMap would only work if we keep the same type T all along. Which is a special case more than the general case.
I realize that you most likely gave here a very simplified sample, but here's how I would do it:
function populateTransaction({initial: Initial, amount: number, date: Date}) {
return new Transaction(initial, amount, date);
}
// {initial: Either<E, Initial>, amount: Either<E, number>, date: Either<E, Date>} => Either<Vector<E>, Transaction>
const populateEitherTx = Either.liftApAcc(populateTransaction);
const amount = initial.map(computeAmount);
const date = initial.map(computeDate);
return populateEitherTx({initial, amount, date});
However I feel that flatMap for a validation/either accumulation purpose is a bit artificial, because the point is that you're supposed to transform the value, meaning often change the type of the value you work on.
Yeah, I think you're right there. Indeed even in my case the types are changing - e.g. we go from
Partial<FinancialTransaction> & Pick<FinancialTransaction, "transactionId">
to
Partial<FinancialTransaction> & Pick<FinancialTransaction, "transactionId" | "amount">
and then likewise we add on the date.
Thanks for taking the time to respond & your suggestion, I'll give it a go. Feel free to close this issue 💚
I've got some code like this
However I'd like to change this so that we accumulate the errors - at the moment, it stops as soon as it ends in a left state. I think normally I'd do this with a
Validation
type, however prelude-ts is missing one currently.I can't seem to get my head around how to achieve this with
Either.sequenceAcc
orEither.liftApAcc