diff options
Diffstat (limited to 'u/trace/itrace.ts')
-rw-r--r-- | u/trace/itrace.ts | 75 |
1 files changed, 48 insertions, 27 deletions
diff --git a/u/trace/itrace.ts b/u/trace/itrace.ts index 8cf123a..9c33ad2 100644 --- a/u/trace/itrace.ts +++ b/u/trace/itrace.ts @@ -1,69 +1,90 @@ import type { Mapper, SideEffect, Supplier } from '@emprespresso/pengueno'; -// the "thing" every Trace writer must "trace()" +/** + * the "thing" every Trace writer must "trace()". + */ type BaseTraceWith = string; export type ITraceWith<T> = BaseTraceWith | T; export interface ITrace<TraceWith> { - addTrace: Mapper<ITraceWith<TraceWith>, ITrace<TraceWith>>; + /** + * creates a new trace scope which inherits from this trace. + */ + traceScope: Mapper<ITraceWith<TraceWith>, ITrace<TraceWith>>; + + /** + * does the tracing. + */ trace: SideEffect<ITraceWith<TraceWith>>; } -export type ITraceableTuple<T, TraceWith> = [T, BaseTraceWith | TraceWith]; -export type ITraceableMapper<T, _T, TraceWith, W = ITraceable<T, TraceWith>> = (w: W) => _T; +export type ITraceableTuple<T, TraceWith> = { item: T; trace: BaseTraceWith | TraceWith }; +export type ITraceableMapper<T, _T, TraceWith> = (w: ITraceable<T, TraceWith>) => _T; export interface ITraceable<T, Trace = BaseTraceWith> { readonly trace: ITrace<Trace>; - get: Supplier<T>; - move: <_T>(t: _T) => ITraceable<_T, Trace>; - map: <_T>(mapper: ITraceableMapper<T, _T, Trace>) => ITraceable<_T, Trace>; - bimap: <_T>(mapper: ITraceableMapper<T, ITraceableTuple<_T, Array<Trace> | Trace>, Trace>) => ITraceable<_T, Trace>; - peek: (peek: ITraceableMapper<T, void, Trace>) => ITraceable<T, Trace>; - flatMap: <_T>(mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>) => ITraceable<_T, Trace>; - flatMapAsync<_T>( + readonly get: Supplier<T>; + + readonly move: <_T>(t: _T) => ITraceable<_T, Trace>; + readonly map: <_T>(mapper: ITraceableMapper<T, _T, Trace>) => ITraceable<_T, Trace>; + readonly bimap: <_T>(mapper: ITraceableMapper<T, ITraceableTuple<_T, Trace>, Trace>) => ITraceable<_T, Trace>; + readonly coExtend: <_T>( + mapper: ITraceableMapper<T, ReadonlyArray<_T>, Trace>, + ) => ReadonlyArray<ITraceable<_T, Trace>>; + readonly peek: (peek: ITraceableMapper<T, void, Trace>) => ITraceable<T, Trace>; + + readonly traceScope: (mapper: ITraceableMapper<T, Trace, Trace>) => ITraceable<T, Trace>; + + readonly flatMap: <_T>(mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>) => ITraceable<_T, Trace>; + readonly flatMapAsync: <_T>( mapper: ITraceableMapper<T, Promise<ITraceable<_T, Trace>>, Trace>, - ): ITraceable<Promise<_T>, Trace>; + ) => ITraceable<Promise<_T>, Trace>; } -export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> { +export class TraceableImpl<T, Trace> implements ITraceable<T, Trace> { protected constructor( private readonly item: T, - public readonly trace: ITrace<TraceWith>, + public readonly trace: ITrace<Trace>, ) {} - public map<_T>(mapper: ITraceableMapper<T, _T, TraceWith>) { + public map<_T>(mapper: ITraceableMapper<T, _T, Trace>) { const result = mapper(this); return new TraceableImpl(result, this.trace); } - public flatMap<_T>(mapper: ITraceableMapper<T, ITraceable<_T, TraceWith>, TraceWith>): ITraceable<_T, TraceWith> { + public coExtend<_T>(mapper: ITraceableMapper<T, ReadonlyArray<_T>, Trace>): ReadonlyArray<ITraceable<_T, Trace>> { + const results = mapper(this); + return Array.from(results).map((result) => this.move(result)); + } + + public flatMap<_T>(mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>): ITraceable<_T, Trace> { return mapper(this); } public flatMapAsync<_T>( - mapper: ITraceableMapper<T, Promise<ITraceable<_T, TraceWith>>, TraceWith>, - ): ITraceable<Promise<_T>, TraceWith> { + mapper: ITraceableMapper<T, Promise<ITraceable<_T, Trace>>, Trace>, + ): ITraceable<Promise<_T>, Trace> { return new TraceableImpl( mapper(this).then((t) => t.get()), this.trace, ); } - public peek(peek: ITraceableMapper<T, void, TraceWith>) { + public traceScope(mapper: ITraceableMapper<T, Trace, Trace>): ITraceable<T, Trace> { + return new TraceableImpl(this.get(), this.trace.traceScope(mapper(this))); + } + + public peek(peek: ITraceableMapper<T, void, Trace>) { peek(this); return this; } - public move<_T>(t: _T): ITraceable<_T, TraceWith> { + public move<_T>(t: _T): ITraceable<_T, Trace> { return this.map(() => t); } - public bimap<_T>(mapper: ITraceableMapper<T, ITraceableTuple<_T, Array<TraceWith> | TraceWith>, TraceWith>) { - const [item, trace] = mapper(this); - const traces = Array.isArray(trace) ? trace : [trace]; - return new TraceableImpl( - item, - traces.reduce((trace, _trace) => trace.addTrace(_trace), this.trace), - ); + public bimap<_T>(mapper: ITraceableMapper<T, ITraceableTuple<_T, Trace>, Trace>) { + const { item, trace: _trace } = mapper(this); + return this.move(item).traceScope(() => <Trace>_trace); } public get() { |