summaryrefslogtreecommitdiff
path: root/u/types/fn/either.ts
diff options
context:
space:
mode:
Diffstat (limited to 'u/types/fn/either.ts')
-rw-r--r--u/types/fn/either.ts143
1 files changed, 0 insertions, 143 deletions
diff --git a/u/types/fn/either.ts b/u/types/fn/either.ts
deleted file mode 100644
index 0f65859..0000000
--- a/u/types/fn/either.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-import {
- BiMapper,
- IOptional,
- type Mapper,
- Optional,
- Predicate,
- type Supplier,
- Tagged,
- isTagged,
-} from '@emprespresso/pengueno';
-
-export const IEitherTag = 'IEither' as const;
-export type IEitherTag = typeof IEitherTag;
-export const isEither = <E, T>(o: unknown): o is IEither<E, T> => isTagged(o, IEitherTag);
-export interface IEither<E, T> extends Tagged<IEitherTag> {
- readonly left: Supplier<IOptional<E>>;
- readonly right: Supplier<IOptional<T>>;
-
- readonly mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
- readonly filter: (mapper: Predicate<T>) => IEither<E, T>;
- readonly mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
- readonly mapBoth: <_E, _T>(errBranch: Mapper<E, _E>, okBranch: Mapper<T, _T>) => IEither<_E, _T>;
-
- readonly flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
- readonly flatMapAsync: <_T>(mapper: Mapper<T, Promise<IEither<E, _T>>>) => Promise<IEither<E, _T>>;
-
- readonly moveRight: <_T>(t: _T) => IEither<E, _T>;
- readonly fold: <_T>(leftFolder: Mapper<E, _T>, rightFolder: Mapper<T, _T>) => _T;
- readonly joinRight: <O, _T>(other: IEither<E, O>, mapper: (a: O, b: T) => _T) => IEither<E, _T>;
- readonly joinRightAsync: <O, _T>(
- other: (() => Promise<IEither<E, O>>) | Promise<IEither<E, O>>,
- mapper: (a: O, b: T) => _T,
- ) => Promise<IEither<E, _T>>;
-}
-
-const ELeftTag = 'E.Left' as const;
-type ELeftTag = typeof ELeftTag;
-export const isLeft = <E>(o: unknown): o is Left<E> => isTagged(o, ELeftTag);
-interface Left<E> extends Tagged<ELeftTag> {
- err: E;
-}
-
-const ERightTag = 'E.Right' as const;
-type ERightTag = typeof ERightTag;
-export const isRight = <T>(o: unknown): o is Right<T> => isTagged(o, ERightTag);
-interface Right<T> extends Tagged<ERightTag> {
- ok: T;
-}
-
-class _Tagged implements Tagged<IEitherTag> {
- protected constructor(public readonly _tag = IEitherTag) {}
-}
-
-export class Either<E, T> extends _Tagged implements IEither<E, T> {
- protected constructor(private readonly self: Left<E> | Right<T>) {
- super();
- }
-
- public moveRight<_T>(t: _T) {
- return this.mapRight(() => t);
- }
-
- public mapBoth<_E, _T>(errBranch: Mapper<E, _E>, okBranch: Mapper<T, _T>): IEither<_E, _T> {
- if (isLeft(this.self)) return Either.left(errBranch(this.self.err));
- return Either.right(okBranch(this.self.ok));
- }
-
- public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
- if (isRight(this.self)) return Either.right(mapper(this.self.ok));
- return Either.left(this.self.err);
- }
-
- public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
- if (isLeft(this.self)) return Either.left(mapper(this.self.err));
- return Either.right(this.self.ok);
- }
-
- public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
- if (isRight(this.self)) return mapper(this.self.ok);
- return Either.left<E, _T>(this.self.err);
- }
-
- public filter(mapper: Predicate<T>): IEither<E, T> {
- if (isLeft(this.self)) return Either.left<E, T>(this.self.err);
- return Either.fromFailable<E, T>(() => this.right().filter(mapper).get());
- }
-
- public async flatMapAsync<_T>(mapper: Mapper<T, Promise<IEither<E, _T>>>): Promise<IEither<E, _T>> {
- if (isLeft(this.self)) return Promise.resolve(Either.left(this.self.err));
- return await mapper(this.self.ok).catch((err) => Either.left(err));
- }
-
- public fold<_T>(leftFolder: Mapper<E, _T>, rightFolder: Mapper<T, _T>): _T {
- if (isLeft(this.self)) return leftFolder(this.self.err);
- return rightFolder(this.self.ok);
- }
-
- public left(): IOptional<E> {
- if (isLeft(this.self)) return Optional.from(this.self.err) as IOptional<E>;
- return Optional.none();
- }
-
- public right(): IOptional<T> {
- if (isRight(this.self)) return Optional.from(this.self.ok) as IOptional<T>;
- return Optional.none();
- }
-
- public joinRight<O, _T>(other: IEither<E, O>, mapper: BiMapper<O, T, _T>) {
- return this.flatMap((t) => other.mapRight((o) => mapper(o, t)));
- }
-
- public joinRightAsync<O, _T>(
- other: Supplier<Promise<IEither<E, O>>> | Promise<IEither<E, O>>,
- mapper: BiMapper<O, T, _T>,
- ) {
- return this.flatMapAsync(async (t) => {
- const o = typeof other === 'function' ? other() : other;
- return await o.then((other) => other.mapRight((o) => mapper(o, t)));
- });
- }
-
- static left<E, T>(e: E): IEither<E, T> {
- return new Either({ err: e, _tag: ELeftTag });
- }
-
- static right<E, T>(t: T): IEither<E, T> {
- return new Either({ ok: t, _tag: ERightTag });
- }
-
- static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
- try {
- return Either.right(s());
- } catch (e) {
- return Either.left(e as E);
- }
- }
-
- static async fromFailableAsync<E, T>(s: Supplier<Promise<T>> | Promise<T>): Promise<IEither<E, T>> {
- return await (typeof s === 'function' ? s() : s)
- .then((t: T) => Either.right<E, T>(t))
- .catch((e: E) => Either.left<E, T>(e));
- }
-}