Basic structures

This commit is contained in:
2024-07-30 22:36:22 +03:00
parent 5ce782aa0f
commit 1c70da5f3b
16 changed files with 885 additions and 16 deletions
+30
View File
@@ -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
View File
@@ -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;
+4
View File
@@ -0,0 +1,4 @@
export * from './core';
export * from './bool';
export * from './num';
export * from './list';
+50
View File
@@ -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
View File
@@ -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))));