Basic structures
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
import { Lazy, _ } from './core';
|
||||
|
||||
export type Bool = <T>(t: Lazy<T>) => (f: Lazy<T>) => Lazy<T>;
|
||||
|
||||
export const True: Lazy<Bool>
|
||||
= _(t => _ => t) as Lazy<Bool>;
|
||||
|
||||
export const False: Lazy<Bool>
|
||||
= _(_ => f => f);
|
||||
|
||||
export const iif: <T>(b: Lazy<Bool>) => (t: Lazy<T>) => (f: Lazy<T>) => Lazy<T>
|
||||
= b => t => f => b.then(b => b(t)(f));
|
||||
|
||||
export const not: (b: Lazy<Bool>) => Lazy<Bool>
|
||||
= b => b.then(b => b(False)(True));
|
||||
|
||||
export const and: (l: Lazy<Bool>) => (r: Lazy<Bool>) => Lazy<Bool>
|
||||
= l => r => l.then(l => l(r)(False));
|
||||
|
||||
export const or: (l: Lazy<Bool>) => (r: Lazy<Bool>) => Lazy<Bool>
|
||||
= l => r => l.then(l => l(True)(r));
|
||||
|
||||
export const xor: (l: Lazy<Bool>) => (r: Lazy<Bool>) => Lazy<Bool>
|
||||
= l => r => l.then(l => l(not(r))(r));
|
||||
|
||||
export const fromBoolean: (b: boolean) => Lazy<Bool>
|
||||
= b => b ? True : False;
|
||||
|
||||
export const toBoolean: (b: Lazy<Bool>) => Lazy<boolean>
|
||||
= b => b.then(b => b(_(true))(_(false)));
|
||||
+44
-1
@@ -1 +1,44 @@
|
||||
export const id = <T>(v: T) => v;
|
||||
export class Lazy<T> {
|
||||
protected _value?: T;
|
||||
|
||||
constructor(private _eval: () => T) { }
|
||||
|
||||
public evaluated: boolean = false;
|
||||
|
||||
public get value(): T {
|
||||
if (this.evaluated) {
|
||||
return this._value!;
|
||||
}
|
||||
this.evaluated = true;
|
||||
return this._value = this._eval();
|
||||
}
|
||||
|
||||
public then<R>(f: (v: T) => Lazy<R>): Lazy<R> {
|
||||
return new Lazy(() => f(this.value).value);
|
||||
}
|
||||
}
|
||||
|
||||
type Choice = <T>(t: Lazy<T>) => (f: Lazy<T>) => Lazy<T>;
|
||||
|
||||
export class LazyChoice extends Lazy<Choice> {
|
||||
public call<T>(l: LazyChoice): (r: LazyChoice) => LazyChoice;
|
||||
public call<T>(l: Lazy<T>): (r: Lazy<T>) => Lazy<T>;
|
||||
public call<T>(l: Lazy<T> | LazyChoice): (r: Lazy<T> | LazyChoice) => Lazy<T> | LazyChoice {
|
||||
return l instanceof LazyChoice
|
||||
? (r: LazyChoice) => new LazyChoice(() => this.value(l)(r).value)
|
||||
: (r: Lazy<T>) => this.then(c => c(l)(r));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const _ = <T>(v: T): Lazy<T> => new Lazy(() => v);
|
||||
export const $ = <T>(v: Lazy<T>): T => v.value;
|
||||
|
||||
export const undef: Lazy<any> = new Lazy(() => {
|
||||
throw new Error('undefined');
|
||||
});
|
||||
|
||||
export const id: <T>(v: Lazy<T>) => Lazy<T>
|
||||
= v => v;
|
||||
export const cnst: <T> (v: Lazy<T>) => (_: Lazy<unknown>) => Lazy<T>
|
||||
= v => _ => v;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './core';
|
||||
export * from './bool';
|
||||
export * from './num';
|
||||
export * from './list';
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
import { Lazy, _, cnst, id, undef } from './core';
|
||||
import { fromNumber, Num, toNumber } from './num';
|
||||
import { Bool, iif } from './bool';
|
||||
|
||||
export type List<T> = <R>(z: Lazy<R>) => (f: (x: Lazy<T>) => (xs: Lazy<List<T>>) => Lazy<R>) => Lazy<R>;
|
||||
|
||||
export const Nil: Lazy<List<any>>
|
||||
= _<List<any>>(z => _ => z);
|
||||
|
||||
export const Cons: <T>(x: Lazy<T>) => (xs: Lazy<List<T>>) => Lazy<List<T>>
|
||||
= <T>(x: Lazy<T>) => (xs: Lazy<List<T>>) => _<List<T>>(_ => f => f(x)(xs));
|
||||
|
||||
export const cons: <T>(x: Lazy<T>) => (xs: Lazy<List<T>>) => Lazy<List<T>>
|
||||
= Cons;
|
||||
|
||||
export const head: <T>(xs: Lazy<List<T>>) => Lazy<T>
|
||||
= xs => xs.then(xs => xs(undef)(cnst));
|
||||
|
||||
export const tail: <T>(xs: Lazy<List<T>>) => Lazy<List<T>>
|
||||
= xs => xs.then(xs => xs(undef)(_ => id));
|
||||
|
||||
export const foldl: <T, R>(f: (a: Lazy<R>) => (x: Lazy<T>) => Lazy<R>) => (z: Lazy<R>) => (xs: Lazy<List<T>>) => Lazy<R>
|
||||
= f => z => xs => xs.then(xs => xs(z)(x => xs => foldl(f)(f(z)(x))(xs)));
|
||||
|
||||
export const foldlz: <T>(f: (a: Lazy<T>) => (x: Lazy<T>) => Lazy<T>) => (xs: Lazy<List<T>>) => Lazy<T>
|
||||
= f => xs => xs.then(xs => xs(undef)(foldl(f)));
|
||||
|
||||
export const foldr: <T, R>(f: (x: Lazy<T>) => (a: Lazy<R>) => Lazy<R>) => (z: Lazy<R>) => (xs: Lazy<List<T>>) => Lazy<R>
|
||||
= f => z => xs => xs.then(xs => xs(z)(x => xs => f(x)(foldr(f)(z)(xs))));
|
||||
|
||||
export const foldrz: <T>(f: (x: Lazy<T>) => (a: Lazy<T>) => Lazy<T>) => (xs: Lazy<List<T>>) => Lazy<T>
|
||||
= _ => _ => undef;
|
||||
|
||||
export const map: <T, R>(f: (x: Lazy<T>) => Lazy<R>) => (xs: Lazy<List<T>>) => Lazy<List<R>>
|
||||
= f => xs => xs.then(xs => xs(Nil)(x => xs => Cons(f(x))(map(f)(xs))));
|
||||
|
||||
export const filter: <T>(f: (x: Lazy<T>) => Lazy<Bool>) => (xs: Lazy<List<T>>) => Lazy<List<T>>
|
||||
= <T>(f: (x: Lazy<T>) => Lazy<Bool>) => (xs: Lazy<List<T>>) => xs.then(xs => xs(Nil)(x => xs => iif<List<T>>(f(x))(Cons(x)(filter(f)(xs)))(filter(f)(xs))));
|
||||
|
||||
export const fromArray: <T>(xs: T[]) => Lazy<List<T>>
|
||||
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(_(xs[0]))(fromArray(xs.slice(1))).value);
|
||||
|
||||
export const fromNumberArray: (xs: number[]) => Lazy<List<Num>>
|
||||
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(fromNumber(xs[0]))(fromNumberArray(xs.slice(1))).value);
|
||||
|
||||
export const toArray: <T>(xs: Lazy<List<T>>) => Lazy<T[]>
|
||||
= <T>(xs: Lazy<List<T>>) => xs.then(xs => xs(_([] as T[]))(x => xs => _([x.value, ...toArray(xs).value])));
|
||||
|
||||
export const toNumberArray: (xs: Lazy<List<Num>>) => Lazy<number[]>
|
||||
= xs => xs.then(xs => xs(_([] as number[]))(x => xs => _([toNumber(x).value, ...toNumberArray(xs).value])));
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import { Bool, not, True } from './bool';
|
||||
import { Lazy, _, id } from './core';
|
||||
|
||||
export type Num = <T>(z: Lazy<T>) => (n: (p: Lazy<Num>) => Lazy<T>) => Lazy<T>;
|
||||
|
||||
export const Zero: Lazy<Num>
|
||||
= _<Num>(z => _ => z);
|
||||
|
||||
export const Succ: (p: Lazy<Num>) => Lazy<Num>
|
||||
= p => _(_ => n => n(p));
|
||||
|
||||
export const ifz: <T>(n: Lazy<Num>) => (t: Lazy<T>) => (f: Lazy<T>) => Lazy<T>
|
||||
= n => t => f => n.then(n => n(t)(_ => f));
|
||||
|
||||
export const succ: (n: Lazy<Num>) => Lazy<Num>
|
||||
= Succ;
|
||||
|
||||
export const pred: (n: Lazy<Num>) => Lazy<Num>
|
||||
= n => n.then(n => n(Zero)(id));
|
||||
|
||||
export const even: (n: Lazy<Num>) => Lazy<Bool>
|
||||
= n => n.then(n => n(True)(odd));
|
||||
|
||||
export const odd: (n: Lazy<Num>) => Lazy<Bool>
|
||||
= n => not(even(n));
|
||||
|
||||
export const sum: (l: Lazy<Num>) => (r: Lazy<Num>) => Lazy<Num>
|
||||
= l => r => r.then(r => r(l)(sum(Succ(l))));
|
||||
|
||||
export const sub: (l: Lazy<Num>) => (r: Lazy<Num>) => Lazy<Num>
|
||||
= l => r => r.then(r => r(l)(pr => l.then(l => l(Zero)(pl => sub(pl)(pr)))));
|
||||
|
||||
export const mul: (l: Lazy<Num>) => (r: Lazy<Num>) => Lazy<Num>
|
||||
= l => r => l.then(l => l(Zero)(pl => sum(r)(mul(pl)(r))));
|
||||
|
||||
export const fromNumber: (n: number) => Lazy<Num>
|
||||
= n => !n ? Zero : new Lazy(() => Succ(fromNumber(n - 1)).value);
|
||||
|
||||
export const toNumber: (n: Lazy<Num>) => Lazy<number>
|
||||
= n => n.then(n => n(_(0))(p => toNumber(p).then(p => _(1 + p))));
|
||||
Reference in New Issue
Block a user