You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
29 lines
1.1 KiB
29 lines
1.1 KiB
type F = (v: L) => L<any>;
|
|
|
|
export type L<T extends F = F> = T & { run: () => T };
|
|
|
|
const defer: <T extends F>(run: () => T) => L<T> = <T extends F>(run: () => T) =>
|
|
Object.assign(((p: Parameters<T>[0]): ReturnType<T> => {
|
|
let v: F;
|
|
return defer(() => run()(defer(() => v ??= p.run())).run());
|
|
}) as T, { run });
|
|
|
|
export const _ = <T extends F>(v: T): L<T> => defer(() => v);
|
|
|
|
export const fromNative: <T>(v: T) => L<any>
|
|
= v => defer(() => v as any);
|
|
export const toNative: <T>(v: L<any>) => T
|
|
= <T>(v: L<any>) => v.run() as T;
|
|
|
|
export const y = (f: () => L<F>) => defer(() => f().run());
|
|
|
|
export const undef: any = defer(() => { throw new Error('undefined'); });
|
|
|
|
export const id: L<<T extends L>(v: T) => T>
|
|
= _(v => v);
|
|
export const cnst: L<<T extends L>(v: T) => L<(_: unknown) => T>>
|
|
= _(v => _(_ => v)) as L<<T extends L>(v: T) => L<(_: unknown) => T>>;
|
|
export const pipe: L<<A extends L, B extends L, C extends L>(f: L<(v: B) => C>) => L<(g: L<(v: A) => B>) => L<(v: A) => C>>>
|
|
= _(<A extends L, B extends L, C extends L>(f: L<(v: B) => C>) =>
|
|
_((g: L<(v: A) => B>) =>
|
|
_((v: A) => f(g(v)))));
|
|
|