Add do notation for either
This commit is contained in:
parent
75368c8ef8
commit
e696e5d9d2
@ -14,15 +14,55 @@ export const right = <A>(a: A): Either<A, never> => ({
|
|||||||
|
|
||||||
// Operations
|
// Operations
|
||||||
export const eitherMap =
|
export const eitherMap =
|
||||||
<E, A, B>(f: (a: A) => B) => (fa: Either<A, E>): Either<B, E> =>
|
<A, B, E>(f: (a: A) => B) => (fa: Either<A, E>): Either<B, E> =>
|
||||||
fa._tag === 'Right' ? right(f(fa.right)) : fa
|
fa._tag === 'Right' ? right(f(fa.right)) : fa
|
||||||
|
|
||||||
export const eitherChain =
|
export const eitherChain =
|
||||||
<E, A, B>(f: (a: A) => Either<B, E>) =>
|
<A, B, E>(f: (a: A) => Either<B, E>) => (fa: Either<A, E>): Either<B, E> =>
|
||||||
(fa: Either<A, E>): Either<B, E> =>
|
|
||||||
fa._tag === 'Right' ? f(fa.right) : fa
|
fa._tag === 'Right' ? f(fa.right) : fa
|
||||||
|
|
||||||
export const fold =
|
export const fold =
|
||||||
<A, B, E>(onLeft: (e: E) => B, onRight: (a: A) => B) =>
|
<A, B, E>(onLeft: (e: E) => B, onRight: (a: A) => B) =>
|
||||||
(fa: Either<A, E>): B =>
|
(fa: Either<A, E>): B =>
|
||||||
fa._tag === 'Left' ? onLeft(fa.left) : onRight(fa.right)
|
fa._tag === 'Left' ? onLeft(fa.left) : onRight(fa.right)
|
||||||
|
|
||||||
|
// Do notation
|
||||||
|
export class DoEither<T extends Record<string, unknown>, E> {
|
||||||
|
constructor(private readonly either: Either<T, E>) {}
|
||||||
|
|
||||||
|
bind<K extends string, A>(
|
||||||
|
key: K,
|
||||||
|
fa: Either<A, E>,
|
||||||
|
): DoEither<T & Record<K, A>, E> {
|
||||||
|
const newEither = eitherChain<T, T & Record<K, A>, E>((scope: T) =>
|
||||||
|
eitherMap<A, T & Record<K, A>, E>((a: A) => ({...scope, [key]: a}))(fa)
|
||||||
|
)(this.either)
|
||||||
|
return new DoEither(newEither)
|
||||||
|
}
|
||||||
|
|
||||||
|
return<B>(f: (scope: T) => B): Either<B, E> {
|
||||||
|
return eitherMap<T, B, E>(f)(this.either)
|
||||||
|
}
|
||||||
|
|
||||||
|
done(): Either<T, E> {
|
||||||
|
return this.either
|
||||||
|
}
|
||||||
|
|
||||||
|
do(fa: Either<unknown, E>): DoEither<T, E> {
|
||||||
|
const newEither = eitherChain<T, T, E>((scope: T) =>
|
||||||
|
eitherMap<unknown, T, E>(() => scope)(fa)
|
||||||
|
)(this.either)
|
||||||
|
return new DoEither(newEither)
|
||||||
|
}
|
||||||
|
|
||||||
|
doL(f: (scope: T) => Either<unknown, E>): DoEither<T, E> {
|
||||||
|
const newEither = eitherChain<T, T, E>((scope: T) =>
|
||||||
|
eitherMap<unknown, T, E>(() => scope)(f(scope))
|
||||||
|
)(this.either)
|
||||||
|
return new DoEither(newEither)
|
||||||
|
}
|
||||||
|
|
||||||
|
static start<E>(): DoEither<{}, E> {
|
||||||
|
return new DoEither(right({}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user