summaryrefslogtreecommitdiff
path: root/u/fn
diff options
context:
space:
mode:
Diffstat (limited to 'u/fn')
-rw-r--r--u/fn/callable.ts15
-rw-r--r--u/fn/either.ts62
-rw-r--r--u/fn/mod.ts2
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";