Lambda calculus-like library written in TypeScript.
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.
 
 
jlc/src/core.ts

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)))));