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({}))
+ }
+}