diff options
author | Elizabeth Hunt <me@liz.coffee> | 2025-07-27 18:50:33 -0700 |
---|---|---|
committer | Elizabeth Hunt <me@liz.coffee> | 2025-07-27 19:31:06 -0700 |
commit | 7aa11b7a8abacf81dec20fff21216df35d333756 (patch) | |
tree | 40f6a76c37412cf1c5a67f99a4ee30e3aae863c9 /u/types/fn/either.ts | |
parent | e4df72cd446270cf867ec308995a05e21b3aa601 (diff) | |
download | ci-7aa11b7a8abacf81dec20fff21216df35d333756.tar.gz ci-7aa11b7a8abacf81dec20fff21216df35d333756.zip |
Pulls in pengueno from npm
Diffstat (limited to 'u/types/fn/either.ts')
-rw-r--r-- | u/types/fn/either.ts | 143 |
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)); - } -} |