diff options
Diffstat (limited to 'u/fn')
-rw-r--r-- | u/fn/callable.ts | 15 | ||||
-rw-r--r-- | u/fn/either.ts | 62 | ||||
-rw-r--r-- | u/fn/mod.ts | 2 |
3 files changed, 79 insertions, 0 deletions
diff --git a/u/fn/callable.ts b/u/fn/callable.ts new file mode 100644 index 0000000..2749947 --- /dev/null +++ b/u/fn/callable.ts @@ -0,0 +1,15 @@ +// deno-lint-ignore no-explicit-any +export interface Callable<T = any, ArgT = any> { + (...args: Array<ArgT>): T; +} + +export interface Supplier<T> extends Callable<T, undefined> { + (): T; +} + +export interface SideEffect<T> extends Callable<void, T> { +} + +export interface Mapper<T, U> extends Callable<U, T> { + (t: T): U; +} diff --git a/u/fn/either.ts b/u/fn/either.ts new file mode 100644 index 0000000..eaf77fd --- /dev/null +++ b/u/fn/either.ts @@ -0,0 +1,62 @@ +import type { Mapper, Supplier } from "./mod.ts"; + +export interface IEither<E, T> { + mapBoth: <Ee, Tt>( + errBranch: Mapper<E, Ee>, + okBranch: Mapper<T, Tt>, + ) => IEither<Ee, Tt>; + flatMap: <Tt>(mapper: Mapper<T, IEither<E, Tt>>) => IEither<E, Tt>; + mapRight: <Tt>(mapper: Mapper<T, Tt>) => IEither<E, Tt>; + mapLeft: <Ee>(mapper: Mapper<E, Ee>) => IEither<Ee, T>; +} + +export class Either<E, T> implements IEither<E, T> { + private constructor(private readonly err?: E, private readonly ok?: T) {} + + public mapBoth<Ee, Tt>( + errBranch: Mapper<E, Ee>, + okBranch: Mapper<T, Tt>, + ): Either<Ee, Tt> { + if (this.err) return Either.left(errBranch(this.err)); + return Either.right(okBranch(this.ok!)); + } + + public flatMap<Tt>(mapper: Mapper<T, Either<E, Tt>>) { + if (this.ok) return mapper(this.ok); + return Either.left<E, Tt>(this.err!); + } + + public mapRight<Tt>(mapper: Mapper<T, Tt>): IEither<E, Tt> { + if (this.ok) return Either.right(mapper(this.ok)); + return Either.left<E, Tt>(this.err!); + } + + public mapLeft<Ee>(mapper: Mapper<E, Ee>) { + if (this.err) return Either.left<Ee, T>(mapper(this.err)); + return Either.right<Ee, T>(this.ok!); + } + + static left<E, T>(e: E) { + return new Either<E, T>(e); + } + + static right<E, T>(t: T) { + return new Either<E, T>(undefined, t); + } + + static fromFailable<E, T>(s: Supplier<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>) { + try { + return Either.right<E, T>(await s); + } catch (e) { + return Either.left<E, T>(e as E); + } + } +} diff --git a/u/fn/mod.ts b/u/fn/mod.ts new file mode 100644 index 0000000..f0fbe88 --- /dev/null +++ b/u/fn/mod.ts @@ -0,0 +1,2 @@ +export * from "./callable.ts"; +export * from "./either.ts"; |