summaryrefslogtreecommitdiff
path: root/u/trace/itrace.ts
diff options
context:
space:
mode:
Diffstat (limited to 'u/trace/itrace.ts')
-rw-r--r--u/trace/itrace.ts72
1 files changed, 72 insertions, 0 deletions
diff --git a/u/trace/itrace.ts b/u/trace/itrace.ts
new file mode 100644
index 0000000..b483067
--- /dev/null
+++ b/u/trace/itrace.ts
@@ -0,0 +1,72 @@
+import { Mapper, SideEffect } from "../fn/mod.ts";
+
+export interface ITrace<TracingW> {
+ addTrace: Mapper<TracingW, ITrace<TracingW>>;
+ trace: SideEffect<TracingW>;
+}
+
+export type ITraceableTuple<T, Trace> = [T, Trace];
+export type ITraceableMapper<T, Trace, U, W = ITraceable<T, Trace>> = (
+ w: W,
+) => U;
+
+export interface ITraceable<T, Trace> {
+ readonly item: T;
+ readonly trace: ITrace<Trace>;
+
+ move<U>(u: U): ITraceable<U, Trace>;
+ map: <U>(
+ mapper: ITraceableMapper<T, Trace, U>,
+ ) => ITraceable<U, Trace>;
+ bimap: <U>(
+ mapper: ITraceableMapper<T, Trace, ITraceableTuple<U, Trace>>,
+ ) => ITraceable<U, Trace>;
+ peek: (peek: ITraceableMapper<T, Trace, void>) => ITraceable<T, Trace>;
+ flatMap: <U>(
+ mapper: ITraceableMapper<T, Trace, ITraceable<U, Trace>>,
+ ) => ITraceable<U, Trace>;
+ flatMapAsync<U>(
+ mapper: ITraceableMapper<T, Trace, Promise<ITraceable<U, Trace>>>,
+ ): ITraceable<Promise<U>, Trace>;
+}
+
+export class TraceableImpl<T, L> implements ITraceable<T, L> {
+ protected constructor(
+ readonly item: T,
+ readonly trace: ITrace<L>,
+ ) {}
+
+ public map<U>(mapper: ITraceableMapper<T, L, U>) {
+ const result = mapper(this);
+ return new TraceableImpl(result, this.trace);
+ }
+
+ public flatMap<U>(
+ mapper: ITraceableMapper<T, L, ITraceable<U, L>>,
+ ): ITraceable<U, L> {
+ return mapper(this);
+ }
+
+ public flatMapAsync<U>(
+ mapper: ITraceableMapper<T, L, Promise<ITraceable<U, L>>>,
+ ): ITraceable<Promise<U>, L> {
+ return new TraceableImpl(
+ mapper(this).then(({ item }) => item),
+ this.trace,
+ );
+ }
+
+ public peek(peek: ITraceableMapper<T, L, void>) {
+ peek(this);
+ return this;
+ }
+
+ public move<Tt>(t: Tt): ITraceable<Tt, L> {
+ return this.map(() => t);
+ }
+
+ public bimap<U>(mapper: ITraceableMapper<T, L, ITraceableTuple<U, L>>) {
+ const [item, trace] = mapper(this);
+ return new TraceableImpl(item, this.trace.addTrace(trace));
+ }
+}