summaryrefslogtreecommitdiff
path: root/u/fn/either.ts
diff options
context:
space:
mode:
Diffstat (limited to 'u/fn/either.ts')
-rw-r--r--u/fn/either.ts188
1 files changed, 92 insertions, 96 deletions
diff --git a/u/fn/either.ts b/u/fn/either.ts
index 124557c..bf90f16 100644
--- a/u/fn/either.ts
+++ b/u/fn/either.ts
@@ -4,115 +4,111 @@ type IEitherTag = "IEither";
const iEitherTag: IEitherTag = "IEither";
export interface _Either<LeftT, RightT, T> {
- readonly isLeft: LeftT;
- readonly isRight: RightT;
- readonly value: T;
+ readonly isLeft: LeftT;
+ readonly isRight: RightT;
+ readonly value: T;
}
export type Left<E> = _Either<true, false, E>;
export type Right<T> = _Either<false, true, T>;
export interface IEither<E, T> {
- readonly _tag: IEitherTag;
-
- mapBoth: <_E, _T>(
- errBranch: Mapper<E, _E>,
- okBranch: Mapper<T, _T>,
- ) => IEither<_E, _T>;
- fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T;
- moveRight: <_T>(t: _T) => IEither<E, _T>;
- mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
- mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
- flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
- flatMapAsync: <_T>(
- mapper: Mapper<T, Promise<IEither<E, _T>>>,
- ) => Promise<IEither<E, _T>>;
+ readonly _tag: IEitherTag;
+
+ mapBoth: <_E, _T>(
+ errBranch: Mapper<E, _E>,
+ okBranch: Mapper<T, _T>,
+ ) => IEither<_E, _T>;
+ fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T;
+ moveRight: <_T>(t: _T) => IEither<E, _T>;
+ mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
+ mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
+ flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
+ flatMapAsync: <_T>(
+ mapper: Mapper<T, Promise<IEither<E, _T>>>,
+ ) => Promise<IEither<E, _T>>;
}
export class Either<E, T> implements IEither<E, T> {
- private readonly self: Left<E> | Right<T>;
-
- private constructor(
- err?: E,
- ok?: T,
- public readonly _tag: IEitherTag = iEitherTag,
- ) {
- this.self = <Left<E> | Right<T>>{
- isLeft: typeof err !== "undefined",
- isRight: typeof ok !== "undefined",
- value: typeof err !== "undefined" ? err : ok!,
- };
+ private readonly self: Left<E> | Right<T>;
+
+ private constructor(
+ err?: E,
+ ok?: T,
+ public readonly _tag: IEitherTag = iEitherTag,
+ ) {
+ this.self = <Left<E> | Right<T>>{
+ isLeft: typeof err !== "undefined",
+ isRight: typeof ok !== "undefined",
+ value: typeof err !== "undefined" ? err : ok!,
+ };
+ }
+
+ public moveRight<_T>(t: _T) {
+ return this.mapRight(() => t);
+ }
+
+ public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T {
+ return folder(this.self);
+ }
+
+ public mapBoth<_E, _T>(
+ errBranch: Mapper<E, _E>,
+ okBranch: Mapper<T, _T>,
+ ): IEither<_E, _T> {
+ if (this.self.isLeft) return Either.left(errBranch(this.self.value));
+ return Either.right(okBranch(this.self.value));
+ }
+
+ public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
+ if (this.self.isRight) return mapper(this.self.value);
+ return Either.left<E, _T>(this.self.value);
+ }
+
+ public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
+ if (this.self.isRight) return Either.right<E, _T>(mapper(this.self.value));
+ return Either.left<E, _T>(this.self.value);
+ }
+
+ public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
+ if (this.self.isLeft) return Either.left<_E, T>(mapper(this.self.value));
+ return Either.right<_E, T>(this.self.value);
+ }
+
+ public async flatMapAsync<_T>(
+ mapper: Mapper<T, Promise<IEither<E, _T>>>,
+ ): Promise<IEither<E, _T>> {
+ if (this.self.isLeft) {
+ return Promise.resolve(Either.left<E, _T>(this.self.value));
}
-
- public moveRight<_T>(t: _T) {
- return this.mapRight(() => t);
- }
-
- public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T {
- return folder(this.self);
- }
-
- public mapBoth<_E, _T>(
- errBranch: Mapper<E, _E>,
- okBranch: Mapper<T, _T>,
- ): IEither<_E, _T> {
- if (this.self.isLeft) return Either.left(errBranch(this.self.value));
- return Either.right(okBranch(this.self.value));
- }
-
- public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
- if (this.self.isRight) return mapper(this.self.value);
- return Either.left<E, _T>(this.self.value);
- }
-
- public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
- if (this.self.isRight)
- return Either.right<E, _T>(mapper(this.self.value));
- return Either.left<E, _T>(this.self.value);
- }
-
- public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
- if (this.self.isLeft)
- return Either.left<_E, T>(mapper(this.self.value));
- return Either.right<_E, T>(this.self.value);
- }
-
- public async flatMapAsync<_T>(
- mapper: Mapper<T, Promise<IEither<E, _T>>>,
- ): Promise<IEither<E, _T>> {
- if (this.self.isLeft) {
- return Promise.resolve(Either.left<E, _T>(this.self.value));
- }
- return await mapper(this.self.value).catch((err) =>
- Either.left<E, _T>(err),
- );
- }
-
- static left<E, T>(e: E): IEither<E, T> {
- return new Either<E, T>(e, undefined);
- }
- static right<E, T>(t: T): IEither<E, T> {
- return new Either<E, T>(undefined, t);
- }
-
- static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
- try {
- return Either.right<E, T>(s());
- } catch (e) {
- return Either.left<E, T>(e as E);
- }
+ return await mapper(this.self.value).catch((err) =>
+ Either.left<E, _T>(err),
+ );
+ }
+
+ static left<E, T>(e: E): IEither<E, T> {
+ return new Either<E, T>(e, undefined);
+ }
+ static right<E, T>(t: T): IEither<E, T> {
+ return new Either<E, T>(undefined, t);
+ }
+
+ static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
+ try {
+ return Either.right<E, T>(s());
+ } catch (e) {
+ return Either.left<E, T>(e as E);
}
+ }
- static async fromFailableAsync<E, T>(
- s: Promise<T>,
- ): Promise<IEither<E, T>> {
- try {
- return Either.right<E, T>(await s);
- } catch (e) {
- return Either.left<E, T>(e as E);
- }
+ static async fromFailableAsync<E, T>(s: Promise<T>): Promise<IEither<E, T>> {
+ try {
+ return Either.right<E, T>(await s);
+ } catch (e) {
+ return Either.left<E, T>(e as E);
}
+ }
}
export const isEither = <E, T>(o: unknown): o is IEither<E, T> => {
- return isObject(o) && "_tag" in o && o._tag === "IEither";
+ return isObject(o) && "_tag" in o && o._tag === "IEither";
};