Curried lambdas
This commit is contained in:
+13
-13
@@ -1,6 +1,6 @@
|
||||
import { Lazy, Q, V, _ } from './core';
|
||||
import { L, P, _, fromNative, toNative } from './core';
|
||||
|
||||
export type Bool = Lazy<<T extends V>(t: T) => Lazy<(f: T) => T>>;
|
||||
export type Bool = L<<T extends P>(t: T) => L<(f: T) => T>>;
|
||||
|
||||
export const True: Bool
|
||||
= _(t => _(_f => t)) as Bool;
|
||||
@@ -8,23 +8,23 @@ export const True: Bool
|
||||
export const False: Bool
|
||||
= _(_t => _(f => f));
|
||||
|
||||
export const iif: <T extends V>(b: Bool) => Lazy<(t: T) => Lazy<(f: T) => T>>
|
||||
= b => _(t => _(f => b.then(b => b(t).then(e=>e(f)))));
|
||||
export const iif: L<<T extends P>(b: Bool) => L<(t: T) => L<(f: T) => T>>>
|
||||
= _(b => _(t => _(f => b._(t)._(f))));
|
||||
|
||||
export const not: (b: Bool) => Bool
|
||||
= b => b.then(b => b(False).then(e=>e(True)));
|
||||
export const not: L<(b: Bool) => Bool>
|
||||
= _(b => b._(False)._(True));
|
||||
|
||||
export const and: (l: Bool) => Lazy<(r: Bool) => Bool>
|
||||
= l => _(r => l.then(l => l(r).then(e=>e(False))));
|
||||
export const and: L<(l: Bool) => L<(r: Bool) => Bool>>
|
||||
= _(l => _(r => l._(r)._(False)));
|
||||
|
||||
export const or: (l: Bool) => Lazy<(r: Bool) => Bool>
|
||||
= l => _(r => l.then(l => l(True).then(e=>e(r))));
|
||||
export const or: L<(l: Bool) => L<(r: Bool) => Bool>>
|
||||
= _(l => _(r => l._(True)._(r)));
|
||||
|
||||
export const xor: (l: Bool) => Lazy<(r: Bool) => Bool>
|
||||
= l => _(r => l.then(l => l(not(r)).then(e=>e(r))));
|
||||
export const xor: L<(l: Bool) => L<(r: Bool) => Bool>>
|
||||
= _(l => _(r => l._(not._(r))._(r)));
|
||||
|
||||
export const fromBoolean: (b: boolean) => Bool
|
||||
= b => b ? True : False;
|
||||
|
||||
export const toBoolean: (b: Bool) => boolean
|
||||
= b => b.then(b => b(_(true as unknown as Q)).then(e=>e(_(false as unknown as Q)))).value as unknown as boolean;
|
||||
= b => toNative(b._(fromNative(true))._(fromNative(false)));
|
||||
|
||||
+14
-12
@@ -1,4 +1,4 @@
|
||||
export class Lazy<T extends (v: unknown) => Lazy<any>> {
|
||||
export class L<T extends (v: unknown) => L<any>> {
|
||||
protected _value?: T;
|
||||
|
||||
constructor(private _eval: () => T) { }
|
||||
@@ -13,23 +13,25 @@ export class Lazy<T extends (v: unknown) => Lazy<any>> {
|
||||
return this._value = this._eval();
|
||||
}
|
||||
|
||||
public then<R extends V>(f: (v: T) => R): R {
|
||||
return new Lazy(() => f(this.value).value) as R;
|
||||
public get _(): T {
|
||||
return ((p: Parameters<T>[0]) => new L(() => this.value(p).value)) as T;
|
||||
}
|
||||
}
|
||||
|
||||
export type Q = (v: unknown) => Lazy<any>;
|
||||
export type P = L<(v: unknown) => L<any>>;
|
||||
|
||||
export type V = Lazy<(v: unknown) => Lazy<any>>;
|
||||
export const _ = <T extends ((v: unknown) => L<any>)>(v: T): L<T> => new L(() => v);
|
||||
|
||||
export const _ = <T extends (v: unknown) => Lazy<any>>(v: T): Lazy<T> => new Lazy(() => v);
|
||||
export const $ = <T extends (v: unknown) => Lazy<any>>(v: Lazy<T>): T => v.value;
|
||||
export const fromNative: <T>(v: T) => L<any>
|
||||
= v => new L(() => v as any);
|
||||
export const toNative: <T>(v: L<any>) => T
|
||||
= <T>(v: L<any>) => v.value as T;
|
||||
|
||||
export const undef: any = new Lazy(() => {
|
||||
export const undef: any = new L(() => {
|
||||
throw new Error('undefined');
|
||||
});
|
||||
|
||||
export const id: <T extends V>(v: T) => T
|
||||
= v => v;
|
||||
export const cnst: <T extends V> (v: T) => Lazy<(_: unknown) => T>
|
||||
= v => _(_ => v);
|
||||
export const id: L<<T extends P>(v: T) => T>
|
||||
= _(v => v);
|
||||
export const cnst: L<<T extends P>(v: T) => L<(_: unknown) => T>>
|
||||
= _(v => _(_ => v)) as L<<T extends P>(v: T) => L<(_: unknown) => T>>;
|
||||
|
||||
+43
-28
@@ -1,50 +1,65 @@
|
||||
import { Lazy, Q, V, _, undef } from './core';
|
||||
import { fromNumber, Num, toNumber } from './num';
|
||||
import { L, P, _, fromNative, toNative, undef } from './core';
|
||||
import { Num, fromNumber, toNumber } from './num';
|
||||
import { Bool, iif } from './bool';
|
||||
|
||||
export type List<T extends V> = Lazy<<R extends V>(z: R) => Lazy<(f: (x: T) => Lazy<(xs: List<T>) => R>) => R>>;
|
||||
export type List<T extends P> = L<<R extends P>(z: R) => L<(f: L<(x: T) => L<(xs: List<T>) => R>>) => R>>;
|
||||
|
||||
export const Nil: List<any>
|
||||
= _(z => _(_f => z)) as List<any>;
|
||||
|
||||
export const Cons: <T extends V>(x: T) => Lazy<(xs: List<T>) => List<T>>
|
||||
= <T extends V>(x: T) => _((xs: List<T>) => _(_z => _(f => f(x).then(e=>e(xs)))) as List<T>);
|
||||
export const Cons: L<<T extends P>(x: T) => L<(xs: List<T>) => List<T>>>
|
||||
= _(<T extends P>(x: T) => _((xs: List<T>) => _(_z => _(f => f._(x)._(xs))) as List<T>));
|
||||
|
||||
export const cons: <T extends V>(x: T) => Lazy<(xs: List<T>) => List<T>>
|
||||
export const cons: L<<T extends P>(x: T) => L<(xs: List<T>) => List<T>>>
|
||||
= Cons;
|
||||
|
||||
export const head: <T extends V>(xs: List<T>) => T
|
||||
= xs => xs.then(xs => xs(undef).then(e=>e(x=>_(_xs=>x))));
|
||||
export const head: L<<T extends P>(xs: List<T>) => T>
|
||||
= _(xs => xs._(undef)._(_(x => _(_xs => x))));
|
||||
|
||||
export const tail: <T extends V>(xs: List<T>) => List<T>
|
||||
= xs => xs.then(xs => xs(undef).then(e=>e(_x =>_(xs=>xs))));
|
||||
export const tail: L<<T extends P>(xs: List<T>) => List<T>>
|
||||
= _(xs => xs._(undef)._(_(_x => _(xs => xs))));
|
||||
|
||||
export const foldl: <T extends V, R extends V>(f: (a: R) => Lazy<(x: T) => R>) => Lazy<(z: R) => Lazy<(xs: List<T>) => R>>
|
||||
= f => _(z => _(xs => xs.then(xs => xs(z).then(e=>e(x => _(xs => foldl(f).then(e=>e(f(z).then(e=>e(x))).then(e=>e(xs)))))))));
|
||||
export const foldl: L<<T extends P, R extends P>(f: L<(a: R) => L<(x: T) => R>>) => L<(z: R) => L<(xs: List<T>) => R>>>
|
||||
=
|
||||
_(<T extends P, R extends P>(f: L<(a: R) => L<(x: T) => R>>) =>
|
||||
_((z: R) =>
|
||||
_((xs: List<T>) => xs._(z)._(_(x =>
|
||||
_(xs => foldl._(f)._(f._(z)._(x))._(xs)))))));
|
||||
|
||||
export const foldlz: <T extends V>(f: (a: T) => Lazy<(x: T) => T>) => Lazy<(xs: List<T>) => T>
|
||||
= f => _(xs => xs.then(xs => xs(undef).then(e=>e(x=>_(xs=>foldl(f).then(e=>e(x).then(e=>e(xs))))))));
|
||||
export const foldlz: L<<T extends P>(f: L<(a: T) => L<(x: T) => T>>) => L<(xs: List<T>) => T>>
|
||||
=
|
||||
_(<T extends P>(f: L<(a: T) => L<(x: T) => T>>) =>
|
||||
_((xs:List<T>) =>
|
||||
xs._(undef)._(_(x =>
|
||||
_(xs => foldl._(f)._(x)._(xs))))));
|
||||
|
||||
export const foldr: <T extends V, R extends V>(f: (x: T) => Lazy<(a: R) => R>) => Lazy<(z: R) => Lazy<(xs: List<T>) => R>>
|
||||
= f => _(z => _(xs => xs.then(xs => xs(z).then(e=>e(x => _(xs => f(x).then(e=>e(foldr(f).then(e=>e(z).then(e=>e(xs)))))))))));
|
||||
export const foldr: L<<T extends P, R extends P>(f: L<(x: T) => L<(a: R) => R>>) => L<(z: R) => L<(xs: List<T>) => R>>>
|
||||
=
|
||||
_(<T extends P, R extends P>(f: L<(x: T) => L<(a: R) => R>>) =>
|
||||
_((z: R) =>
|
||||
_((xs: List<T>) => xs._(z)._(_(x => _(xs => f._(x)._(foldr._(f)._(z)._(xs))))))));
|
||||
|
||||
export const foldrz: <T extends V>(f: (x: T) => Lazy<(a: T) => T>) => Lazy<(xs: List<T>) => T>
|
||||
= _f => _(_z => undef);
|
||||
export const foldrz: L<<T extends P>(f: L<(x: T) => L<(a: T) => T>>) => L<(xs: List<T>) => T>>
|
||||
= _(_f => _(_z => undef));
|
||||
|
||||
export const map: <T extends V, R extends V>(f: (x: T) => R) => Lazy<(xs: List<T>) => List<R>>
|
||||
= f => _(xs => xs.then(xs => xs(Nil).then(e=>e(x =>_( xs => Cons(f(x)).then(e=>e(map(f).then(e=>e(xs)))))))));
|
||||
export const map: L<<T extends P, R extends P>(f: L<(x: T) => R>) => L<(xs: List<T>) => List<R>>>
|
||||
=
|
||||
_(<T extends P, R extends P>(f: L<(x: T) => R>) =>
|
||||
_((xs: List<T>) => xs._(Nil)._(_(x => _(xs => Cons._(f._(x))._(map._(f)._(xs)))))));
|
||||
|
||||
export const filter: <T extends V>(f: (x: T) => Bool) => Lazy<(xs: List<T>) => List<T>>
|
||||
= <T extends V>(f: (x: T) => Bool) => _((xs: List<T>) => xs.then(xs => xs(Nil).then(e=>e(x => _(xs => iif<List<T>>(f(x)).then(e=>e(Cons(x).then(e=>e(filter(f).then(e=>e(xs))))).then(e=>e(filter(f).then(e=>e(xs))))))))));
|
||||
export const filter: L<<T extends P>(f: L<(x: T) => Bool>) => L<(xs: List<T>) => List<T>>>
|
||||
=
|
||||
_(<T extends P>(f: L<(x: T) => Bool>) =>
|
||||
_((xs: List<T>) => xs._(Nil)._(_(x => _(xs => iif._(f._(x))._(Cons._(x)._(filter._(f)._(xs)))._(filter._(f)._(xs)))))));
|
||||
|
||||
export const fromArray: <T extends V>(xs: T[]) => List<T>
|
||||
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(xs[0]).then(e=>e(fromArray(xs.slice(1)))).value);
|
||||
export const fromArray: <T extends P>(xs: T[]) => List<T>
|
||||
= xs => xs.length === 0 ? Nil : Cons._(xs[0])._(new L(() => fromArray(xs.slice(1)).value));
|
||||
|
||||
export const fromNumberArray: (xs: number[]) => List<Num>
|
||||
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(fromNumber(xs[0])).then(e=>e(fromNumberArray(xs.slice(1)))).value);
|
||||
= xs => xs.length === 0 ? Nil : Cons._(fromNumber(xs[0]))._(new L(() => fromNumberArray(xs.slice(1)).value));
|
||||
|
||||
export const toArray: <R extends Q, T extends Lazy<R>>(xs: List<T>) => R[]
|
||||
= <R extends Q, T extends Lazy<R>>(xs: List<T>) => xs.then(xs => xs(_([] as R[] as unknown as Q)).then(e=>e(x => _(xs => _([x.value, ...toArray<R, T>(xs)] as unknown as Q))))).value as unknown as R[];
|
||||
export const toArray: <T extends P>(xs: List<T>) => P[]
|
||||
= xs => toNative(xs._(fromNative([]))._(_(x => _(xs => fromNative([x, ...toArray(xs)])))));
|
||||
|
||||
export const toNumberArray: (xs: List<Num>) => number[]
|
||||
= xs => xs.then(xs => xs(_([] as number[]as unknown as Q)).then(e=>e(x => _(xs => _([toNumber(x), ...toNumberArray(xs)]as unknown as Q))))).value as unknown as number[];
|
||||
= xs => toNative(xs._(fromNative([]))._(_(x => _(xs => fromNative([toNumber(x), ...toNumberArray(xs)])))));
|
||||
|
||||
+22
-22
@@ -1,40 +1,40 @@
|
||||
import { Bool, not, True } from './bool';
|
||||
import { Lazy, Q, V, _, id } from './core';
|
||||
import { Bool, False, True } from './bool';
|
||||
import { L, P, _, fromNative, id, toNative } from './core';
|
||||
|
||||
export type Num = Lazy<<T extends V>(z: T) => Lazy<(n: (p: Num) => T) => T>>;
|
||||
export type Num = L<<T extends P>(z: T) => L<(n: L<(p: Num) => T>) => T>>;
|
||||
|
||||
export const Zero: Num
|
||||
= _(z => _(_n => z)) as Num;
|
||||
|
||||
export const Succ: (p: Num) => Num
|
||||
= p => _(_z => _(n => n(p)));
|
||||
export const Succ: L<(p: Num) => Num>
|
||||
= _(p => _(_z => _(n => n._(p))));
|
||||
|
||||
export const ifz: <T extends V>(n: Num) => Lazy<(t: T) => Lazy<(f: T) => T>>
|
||||
= n => _(t => _(f => n.then(n => n(t).then(e => e(_ => f)))));
|
||||
export const ifz: L<<T extends P>(n: Num) => L<(t: T) => L<(f: T) => T>>>
|
||||
= _(n => _(t => _(f => n._(t)._(_(_ => f)))));
|
||||
|
||||
export const succ: (n: Num) => Num
|
||||
export const succ: L<(n: Num) => Num>
|
||||
= Succ;
|
||||
|
||||
export const pred: (n: Num) => Num
|
||||
= n => n.then(n => n(Zero).then(e=>e(id)));
|
||||
export const pred: L<(n: Num) => Num>
|
||||
= _(n => n._(Zero)._(id));
|
||||
|
||||
export const even: (n: Num) => Bool
|
||||
= n => n.then(n => n(True).then(e=>e(odd)));
|
||||
export const even: L<(n: Num) => Bool>
|
||||
= _(n => n._(True)._(odd));
|
||||
|
||||
export const odd: (n: Num) => Bool
|
||||
= n => not(even(n));
|
||||
export const odd: L<(n: Num) => Bool>
|
||||
= _(n => n._(False)._(even));
|
||||
|
||||
export const sum: (l: Num) => Lazy<(r: Num) => Num>
|
||||
= l => _(r => r.then(r => r(l).then(e=>e(t=>sum(Succ(l)).then(e=>e(t))))));
|
||||
export const sum: L<(l: Num) => L<(r: Num) => Num>>
|
||||
= _(l => _(r => r._(l)._(_(t => sum._(Succ._(l))._(t)))));
|
||||
|
||||
export const sub: (l: Num) => Lazy<(r: Num) => Num>
|
||||
= l => _(r => r.then(r => r(l).then(e=>e(pr => l.then(l => l(Zero).then(e=>e(pl => sub(pl).then(e=>e(pr)))))))));
|
||||
export const sub: L<(l: Num) => L<(r: Num) => Num>>
|
||||
= _(l => _(r => r._(l)._(_(pr => l._(Zero)._(_(pl => sub._(pl)._(pr)))))));
|
||||
|
||||
export const mul: (l: Num) => Lazy<(r: Num) => Num>
|
||||
= l => _(r => l.then(l => l(Zero).then(e=>e(pl => sum(r).then(e=>e(mul(pl).then(e=>e(r))))))));
|
||||
export const mul: L<(l: Num) => L<(r: Num) => Num>>
|
||||
= _(l => _(r => l._(Zero)._(_(pl => sum._(r)._(mul._(pl)._(r))))));
|
||||
|
||||
export const fromNumber: (n: number) => Num
|
||||
= n => !n ? Zero : new Lazy(() => Succ(fromNumber(n - 1)).value);
|
||||
= n => !n ? Zero : Succ._(new L(() => fromNumber(n - 1).value));
|
||||
|
||||
export const toNumber: (n: Num) => number
|
||||
= n => n.then(n => n(_(0 as unknown as Q)).then(e=>e(p => _((1 + toNumber(p)) as unknown as Q)))).value as unknown as number;
|
||||
= n => toNative(n._(fromNative(0))._(_(p => fromNative(1 + toNumber(p)))));
|
||||
|
||||
Reference in New Issue
Block a user