I'm trying to understand the diference between E.altW and E.orElse, but both seem to do the same. For example, I can construct a Semigroup that concatenates parsing functions using either of them:
import * as E from 'fp-ts/Either';
import * as A from 'fp-ts/Array';
import { pipe } from 'fp-ts/function';
import * as S from 'fp-ts/Semigroup';
const parseString = (u: unknown): E.Either<string, string> =>
typeof u === 'string' ? E.right(u) : E.left('not a string');
const parseNumber = (u: unknown): E.Either<string, number> =>
typeof u === 'number' ? E.right(u) : E.left('not a number');
const ParseSemigroup: S.Semigroup<
(u: unknown) => E.Either<string, string | number>
> = {
concat(a, b) {
return (input) =>
pipe(
a(input),
E.altW(() => b(input))
);
},
};
const ParseSemigroup2: S.Semigroup<
(u: unknown) => E.Either<string, number | string>
> = {
concat(a, b) {
return (input) =>
pipe(
a(input),
E.orElse(() => b(input))
);
},
};
const manyParsers = S.concatAll(ParseSemigroup)(parseNumber)([parseString]);
console.log(manyParsers('99'));
const manyParsers2 = S.concatAll(ParseSemigroup2)(parseNumber)([parseString]);
console.log(manyParsers('99'));
And the result is exactly the same, as you can see. When should I use one over the other? or what are the specific usecases of each?
First, one thing to note is that
altWis slightly different fromaltand likewise foronElseWandonElse. TheWsuffix stands for ‘widen’ and it means you can do things like this:where the resulting
Eitherhas a union type inside of it. You can read more about this on the fp-ts FAQ.Here’s the types of
altandonElseand theirWcounterparts:Because TypeScript types can look pretty messy, here’s the same thing but with a Haskell-like syntax:
As you can hopefully see, the main difference between
altandorElseis that the function passed intoorElsetakes in the errorE1. In your case where the function passed toonElseignores/does not use the error,altandonElseare equivalent. In this case,altis the more appropriate function to use here.If you want to return a new
Eitherwith a different error and/or success type, then you should usealtW/orElseW.So, in summary:
orElse/orElseWalt/altWorElseW/altWorElse/altSide note: Alternative
You may have noticed that there’s another difference between
altandorElse: inorElse, the either returned by the function can have a different error typeE2.This is because the
altfunction comes from theAlttypeclass:In the case of
Either, you can think ofHKT<F, A>likeEither<E, A>, so theEhas to be the same both infaandthat.