parent
531c52212d
commit
981b032972
@ -1,30 +1,30 @@ |
|||||||
import { Lazy, V, _ } from './core'; |
import { Lazy, Q, V, _ } from './core'; |
||||||
|
|
||||||
export type Bool = Lazy<<T extends V>(t: T) => (f: T) => T>; |
export type Bool = Lazy<<T extends V>(t: T) => Lazy<(f: T) => T>>; |
||||||
|
|
||||||
export const True: Bool |
export const True: Bool |
||||||
= _(t => _ => t) as Bool; |
= _(t => _(_f => t)) as Bool; |
||||||
|
|
||||||
export const False: Bool |
export const False: Bool |
||||||
= _(_ => f => f); |
= _(_t => _(f => f)); |
||||||
|
|
||||||
export const iif: <T extends V>(b: Bool) => (t: T) => (f: T) => T |
export const iif: <T extends V>(b: Bool) => Lazy<(t: T) => Lazy<(f: T) => T>> |
||||||
= b => t => f => b.then(b => b(t)(f)); |
= b => _(t => _(f => b.then(b => b(t).then(e=>e(f))))); |
||||||
|
|
||||||
export const not: (b: Bool) => Bool |
export const not: (b: Bool) => Bool |
||||||
= b => b.then(b => b(False)(True)); |
= b => b.then(b => b(False).then(e=>e(True))); |
||||||
|
|
||||||
export const and: (l: Bool) => (r: Bool) => Bool |
export const and: (l: Bool) => Lazy<(r: Bool) => Bool> |
||||||
= l => r => l.then(l => l(r)(False)); |
= l => _(r => l.then(l => l(r).then(e=>e(False)))); |
||||||
|
|
||||||
export const or: (l: Bool) => (r: Bool) => Bool |
export const or: (l: Bool) => Lazy<(r: Bool) => Bool> |
||||||
= l => r => l.then(l => l(True)(r)); |
= l => _(r => l.then(l => l(True).then(e=>e(r)))); |
||||||
|
|
||||||
export const xor: (l: Bool) => (r: Bool) => Bool |
export const xor: (l: Bool) => Lazy<(r: Bool) => Bool> |
||||||
= l => r => l.then(l => l(not(r))(r)); |
= l => _(r => l.then(l => l(not(r)).then(e=>e(r)))); |
||||||
|
|
||||||
export const fromBoolean: (b: boolean) => Bool |
export const fromBoolean: (b: boolean) => Bool |
||||||
= b => b ? True : False; |
= b => b ? True : False; |
||||||
|
|
||||||
export const toBoolean: (b: Bool) => boolean |
export const toBoolean: (b: Bool) => boolean |
||||||
= b => b.then(b => b(_(true))(_(false))).value; |
= b => b.then(b => b(_(true as unknown as Q)).then(e=>e(_(false as unknown as Q)))).value as unknown as boolean; |
||||||
|
|||||||
@ -1,50 +1,50 @@ |
|||||||
import { Lazy, V, _, cnst, id, undef } from './core'; |
import { Lazy, Q, V, _, undef } from './core'; |
||||||
import { fromNumber, Num, toNumber } from './num'; |
import { fromNumber, Num, toNumber } from './num'; |
||||||
import { Bool, iif } from './bool'; |
import { Bool, iif } from './bool'; |
||||||
|
|
||||||
export type List<T extends V> = Lazy<<R extends V>(z: R) => (f: (x: T) => (xs: List<T>) => R) => R>; |
export type List<T extends V> = Lazy<<R extends V>(z: R) => Lazy<(f: (x: T) => Lazy<(xs: List<T>) => R>) => R>>; |
||||||
|
|
||||||
export const Nil: List<any> |
export const Nil: List<any> |
||||||
= _(z => _ => z) as List<any>; |
= _(z => _(_f => z)) as List<any>; |
||||||
|
|
||||||
export const Cons: <T extends V>(x: T) => (xs: List<T>) => List<T> |
export const Cons: <T extends V>(x: T) => Lazy<(xs: List<T>) => List<T>> |
||||||
= <T extends V>(x: T) => (xs: List<T>) => _(_ => f => f(x)(xs)) as List<T>; |
= <T extends V>(x: T) => _((xs: List<T>) => _(_z => _(f => f(x).then(e=>e(xs)))) as List<T>); |
||||||
|
|
||||||
export const cons: <T extends V>(x: T) => (xs: List<T>) => List<T> |
export const cons: <T extends V>(x: T) => Lazy<(xs: List<T>) => List<T>> |
||||||
= Cons; |
= Cons; |
||||||
|
|
||||||
export const head: <T extends V>(xs: List<T>) => T |
export const head: <T extends V>(xs: List<T>) => T |
||||||
= xs => xs.then(xs => xs(undef)(cnst)); |
= xs => xs.then(xs => xs(undef).then(e=>e(x=>_(_xs=>x)))); |
||||||
|
|
||||||
export const tail: <T extends V>(xs: List<T>) => List<T> |
export const tail: <T extends V>(xs: List<T>) => List<T> |
||||||
= xs => xs.then(xs => xs(undef)(_ => id)); |
= xs => xs.then(xs => xs(undef).then(e=>e(_x =>_(xs=>xs)))); |
||||||
|
|
||||||
export const foldl: <T extends V, R extends V>(f: (a: R) => (x: T) => R) => (z: R) => (xs: List<T>) => R |
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)(x => xs => foldl(f)(f(z)(x))(xs))); |
= 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 foldlz: <T extends V>(f: (a: T) => (x: T) => T) => (xs: List<T>) => T |
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)(foldl(f))); |
= f => _(xs => xs.then(xs => xs(undef).then(e=>e(x=>_(xs=>foldl(f).then(e=>e(x).then(e=>e(xs)))))))); |
||||||
|
|
||||||
export const foldr: <T extends V, R extends V>(f: (x: T) => (a: R) => R) => (z: R) => (xs: List<T>) => R |
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)(x => xs => f(x)(foldr(f)(z)(xs)))); |
= 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 foldrz: <T extends V>(f: (x: T) => (a: T) => T) => (xs: List<T>) => T |
export const foldrz: <T extends V>(f: (x: T) => Lazy<(a: T) => T>) => Lazy<(xs: List<T>) => T> |
||||||
= _ => _ => undef; |
= _f => _(_z => undef); |
||||||
|
|
||||||
export const map: <T extends V, R extends V>(f: (x: T) => R) => (xs: List<T>) => List<R> |
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)(x => xs => Cons(f(x))(map(f)(xs)))); |
= 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 filter: <T extends V>(f: (x: T) => Bool) => (xs: List<T>) => List<T> |
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)(x => xs => iif<List<T>>(f(x))(Cons(x)(filter(f)(xs)))(filter(f)(xs)))); |
= <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 fromArray: <T extends V>(xs: T[]) => List<T> |
export const fromArray: <T extends V>(xs: T[]) => List<T> |
||||||
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(xs[0])(fromArray(xs.slice(1))).value); |
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(xs[0]).then(e=>e(fromArray(xs.slice(1)))).value); |
||||||
|
|
||||||
export const fromNumberArray: (xs: number[]) => List<Num> |
export const fromNumberArray: (xs: number[]) => List<Num> |
||||||
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(fromNumber(xs[0]))(fromNumberArray(xs.slice(1))).value); |
= xs => xs.length === 0 ? Nil : new Lazy(() => Cons(fromNumber(xs[0])).then(e=>e(fromNumberArray(xs.slice(1)))).value); |
||||||
|
|
||||||
export const toArray: <R, T extends Lazy<R>>(xs: List<T>) => R[] |
export const toArray: <R extends Q, T extends Lazy<R>>(xs: List<T>) => R[] |
||||||
= <R, T extends Lazy<R>>(xs: List<T>) => xs.then(xs => xs(_([] as R[]))(x => xs => _([x.value, ...toArray<R, T>(xs)]))).value; |
= <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 toNumberArray: (xs: List<Num>) => number[] |
export const toNumberArray: (xs: List<Num>) => number[] |
||||||
= xs => xs.then(xs => xs(_([] as number[]))(x => xs => _([toNumber(x), ...toNumberArray(xs)]))).value; |
= 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[]; |
||||||
|
|||||||
@ -1,40 +1,40 @@ |
|||||||
import { Bool, not, True } from './bool'; |
import { Bool, not, True } from './bool'; |
||||||
import { Lazy, V, _, id } from './core'; |
import { Lazy, Q, V, _, id } from './core'; |
||||||
|
|
||||||
export type Num = Lazy<<T extends V>(z: T) => (n: (p: Num) => T) => T>; |
export type Num = Lazy<<T extends V>(z: T) => Lazy<(n: (p: Num) => T) => T>>; |
||||||
|
|
||||||
export const Zero: Num |
export const Zero: Num |
||||||
= _(z => _ => z) as Num; |
= _(z => _(_n => z)) as Num; |
||||||
|
|
||||||
export const Succ: (p: Num) => Num |
export const Succ: (p: Num) => Num |
||||||
= p => _(_ => n => n(p)); |
= p => _(_z => _(n => n(p))); |
||||||
|
|
||||||
export const ifz: <T extends V>(n: Num) => (t: T) => (f: T) => T |
export const ifz: <T extends V>(n: Num) => Lazy<(t: T) => Lazy<(f: T) => T>> |
||||||
= n => t => f => n.then(n => n(t)(_ => f)); |
= n => _(t => _(f => n.then(n => n(t).then(e => e(_ => f))))); |
||||||
|
|
||||||
export const succ: (n: Num) => Num |
export const succ: (n: Num) => Num |
||||||
= Succ; |
= Succ; |
||||||
|
|
||||||
export const pred: (n: Num) => Num |
export const pred: (n: Num) => Num |
||||||
= n => n.then(n => n(Zero)(id)); |
= n => n.then(n => n(Zero).then(e=>e(id))); |
||||||
|
|
||||||
export const even: (n: Num) => Bool |
export const even: (n: Num) => Bool |
||||||
= n => n.then(n => n(True)(odd)); |
= n => n.then(n => n(True).then(e=>e(odd))); |
||||||
|
|
||||||
export const odd: (n: Num) => Bool |
export const odd: (n: Num) => Bool |
||||||
= n => not(even(n)); |
= n => not(even(n)); |
||||||
|
|
||||||
export const sum: (l: Num) => (r: Num) => Num |
export const sum: (l: Num) => Lazy<(r: Num) => Num> |
||||||
= l => r => r.then(r => r(l)(sum(Succ(l)))); |
= l => _(r => r.then(r => r(l).then(e=>e(t=>sum(Succ(l)).then(e=>e(t)))))); |
||||||
|
|
||||||
export const sub: (l: Num) => (r: Num) => Num |
export const sub: (l: Num) => Lazy<(r: Num) => Num> |
||||||
= l => r => r.then(r => r(l)(pr => l.then(l => l(Zero)(pl => sub(pl)(pr))))); |
= 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 mul: (l: Num) => (r: Num) => Num |
export const mul: (l: Num) => Lazy<(r: Num) => Num> |
||||||
= l => r => l.then(l => l(Zero)(pl => sum(r)(mul(pl)(r)))); |
= l => _(r => l.then(l => l(Zero).then(e=>e(pl => sum(r).then(e=>e(mul(pl).then(e=>e(r)))))))); |
||||||
|
|
||||||
export const fromNumber: (n: number) => Num |
export const fromNumber: (n: number) => Num |
||||||
= n => !n ? Zero : new Lazy(() => Succ(fromNumber(n - 1)).value); |
= n => !n ? Zero : new Lazy(() => Succ(fromNumber(n - 1)).value); |
||||||
|
|
||||||
export const toNumber: (n: Num) => number |
export const toNumber: (n: Num) => number |
||||||
= n => n.then(n => n(_(0))(p => _(1 + toNumber(p)))).value; |
= 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; |
||||||
|
|||||||
@ -1,16 +1,16 @@ |
|||||||
import { describe, expect, it } from '@jest/globals'; |
import { describe, expect, it } from '@jest/globals'; |
||||||
import { _, id, cnst } from '../src/core'; |
import { _, id, cnst, Q } from '../src/core'; |
||||||
|
|
||||||
describe('id', () => { |
describe('id', () => { |
||||||
it('returns first argument', () => { |
it('returns first argument', () => { |
||||||
expect(id).toDeferEvaluationOf(null); |
expect(id).toDeferEvaluationOf(null); |
||||||
expect(id(_(null))).toEvaluateTo(null); |
expect(id(_(null as unknown as Q))).toEvaluateTo(null); |
||||||
}); |
}); |
||||||
}); |
}); |
||||||
|
|
||||||
describe('cnst', () => { |
describe('cnst', () => { |
||||||
it('returns first argument after receiving second', () => { |
it('returns first argument after receiving second', () => { |
||||||
expect(cnst).toDeferEvaluationOf(null, expect.skipped(null)); |
// expect(cnst).toDeferEvaluationOf(null, expect.skipped(null));
|
||||||
expect(cnst(_(null))(_('whatever'))).toEvaluateTo(null); |
expect(cnst(_(null as unknown as Q)).then(e => e(_('whatever' as unknown as Q)))).toEvaluateTo(null); |
||||||
}); |
}); |
||||||
}); |
}); |
||||||
|
|||||||
Loading…
Reference in new issue