diff --git a/src/lib/util/basic/either.ts b/src/lib/util/basic/either.ts index 92cc051..a2b372e 100644 --- a/src/lib/util/basic/either.ts +++ b/src/lib/util/basic/either.ts @@ -14,15 +14,55 @@ export const right = (a: A): Either => ({ // Operations export const eitherMap = - (f: (a: A) => B) => (fa: Either): Either => + (f: (a: A) => B) => (fa: Either): Either => fa._tag === 'Right' ? right(f(fa.right)) : fa export const eitherChain = - (f: (a: A) => Either) => - (fa: Either): Either => + (f: (a: A) => Either) => (fa: Either): Either => fa._tag === 'Right' ? f(fa.right) : fa export const fold = (onLeft: (e: E) => B, onRight: (a: A) => B) => (fa: Either): B => fa._tag === 'Left' ? onLeft(fa.left) : onRight(fa.right) + +// Do notation +export class DoEither, E> { + constructor(private readonly either: Either) {} + + bind( + key: K, + fa: Either, + ): DoEither, E> { + const newEither = eitherChain, E>((scope: T) => + eitherMap, E>((a: A) => ({...scope, [key]: a}))(fa) + )(this.either) + return new DoEither(newEither) + } + + return(f: (scope: T) => B): Either { + return eitherMap(f)(this.either) + } + + done(): Either { + return this.either + } + + do(fa: Either): DoEither { + const newEither = eitherChain((scope: T) => + eitherMap(() => scope)(fa) + )(this.either) + return new DoEither(newEither) + } + + doL(f: (scope: T) => Either): DoEither { + const newEither = eitherChain((scope: T) => + eitherMap(() => scope)(f(scope)) + )(this.either) + return new DoEither(newEither) + } + + static start(): DoEither<{}, E> { + return new DoEither(right({})) + } +}