diff --git a/src/bf.ts b/src/bf.ts index 76e425c..ef44be5 100644 --- a/src/bf.ts +++ b/src/bf.ts @@ -1,10 +1,10 @@ -import { L, _, fromNative as __, cnst, id } from './core'; +import { L, _, fromNative as __, cnst, id, pipe } from './core'; import { Bool, iif } from './bool'; import { Num, Zero, ge, ifz, pred, succ } from './num'; import { x00 } from './byte'; import { Char, fromChar as _c, dec as cdec, inc as cinc, eq, ifn } from './char'; import { Pair, first, fst, second, snd, uncurry } from './pair'; -import { List, Nil, cons, head, repeat, set, tail, update } from './list'; +import { List, Nil, cons, head, repeat, set, singleton, tail, update } from './list'; import { Empty, String, get, len, snoc } from './string'; type Program = Pair, String>; @@ -19,12 +19,11 @@ const done: L<(s: State) => Bool> = uncurry(_(p => cnst(uncurry(_(is => _(cs => ge(head(is))(len(cs)))))(p)))); const command: L<(c: String) => L<(s: State) => Bool>> - = _(c => uncurry(_(p => cnst(eq(c)(uncurry(_(is => get(head(is))))(p)))))); + = _(c => uncurry(_(p => cnst(eq(c)(uncurry(pipe(get)(head))(p)))))); const advance: L<(s: State) => State> = first(first(update(succ)(Zero))); - const save: L<(s: State) => State> = first(first(_(is => cons(head(is))(is)))); @@ -41,13 +40,13 @@ const dec: L<(t: State) => State> = second(first(_(t => second(update(cdec)(fst(t)))(t)))); const read: L<(s: State) => Char> - = _(s => uncurry(get)(fst(snd(s)))); + = pipe(pipe(uncurry(get))(fst))(snd); const input: L<(s: State) => State> = second(uncurry(_(t => _(io => Pair(second(set(head(fst(io)))(fst(t)))(t))(first(tail)(io)))))); const output: L<(s: State) => State> - = second(uncurry(_(t => _(io => Pair(t)(second(_(os => snoc(os)(uncurry(get)(t))))(io)))))); + = second(uncurry(_(t => pipe(Pair(t))(second(_(os => snoc(os)(uncurry(get)(t)))))))); const next: L<(t: State) => State> = second(first(first(succ))); @@ -65,10 +64,7 @@ const whlnz: L<(t: State) => State> = _(s => ifn(read(s))(jump(Zero))(save)(s)); const endwhl: L<(t: State) => State> - = _(s => ifn(read(s))(reset(s))(save(restore(s)))); - -const when: L<(c: String) => L<(f: L<(s: State) => State>) => L<(s:State)=>State>>> - = _(c => _(f => _(s => iif(command(c)(s))(f(s))(s)))); + = _(s => ifn(read(s))(reset)(pipe(save)(restore))(s)); const exec: L<(s: State) => State> = _(s => iif(done(s))(s)(exec(advance @@ -83,4 +79,4 @@ const exec: L<(s: State) => State> (id))))))))(s))))); export const run: L<(p: String) => L<(i: String) => String>> - = _(p => _(i => snd(snd(snd(exec(Pair(Pair(cons(Zero)(Nil))(p))(Pair(Pair(Zero)(repeat(x00)))(Pair(i)(Empty))))))))); + = _(p => _(i => snd(snd(snd(exec(Pair(Pair(singleton(Zero))(p))(Pair(Pair(Zero)(repeat(x00)))(Pair(i)(Empty))))))))); diff --git a/src/bool.ts b/src/bool.ts index 265cb84..fbb9155 100644 --- a/src/bool.ts +++ b/src/bool.ts @@ -1,4 +1,4 @@ -import { toNative as $$, L, P, _, fromNative as __, id } from './core'; +import { toNative as $$, L, P, _, fromNative as __, id, pipe } from './core'; import { EQ, GT, LT, Ord } from './ord'; import { String, fromString as _s } from './string'; @@ -29,10 +29,10 @@ export const eq: L<(l: Bool) => L<(r: Bool) => Bool>> = _(l => _(r => l(r)(not(r)))); export const ge: L<(l: Bool) => L<(r: Bool) => Bool>> - = _(l => _(r => not(lt(l)(r)))); + = _(l => pipe(not)(lt(l))); export const gt: L<(l: Bool) => L<(r: Bool) => Bool>> - = _(l => _(r => not(le(l)(r)))); + = _(l => pipe(not)(le(l))); export const and: L<(l: Bool) => L<(r: Bool) => Bool>> = _(l => not(l)(False)); diff --git a/src/char.ts b/src/char.ts index a19be8b..173a809 100644 --- a/src/char.ts +++ b/src/char.ts @@ -1,6 +1,7 @@ -import { L, _ } from './core'; +import { L, _, pipe } from './core'; import { toNumber as $n, Byte, fromNumber as _n, x00 } from './byte'; -import { Empty, String, cons, fromString as _s, wrap } from './string'; +import { singleton } from './list'; +import { String, fromString as _s, wrap } from './string'; export type Char = Byte; @@ -10,7 +11,7 @@ export const Null: Char export { inc, dec, ifz as ifn, cmp, lt, le, eq, ge, gt } from './byte'; export const show: L<(c: Char) => String> - = _(c => wrap(_s('\''))(cons(c)(Empty))); + = _(c => pipe(wrap(_s('\'')))(singleton)(c)); export const fromChar: (c: string) => Char = c => _n(c.charCodeAt(0)); diff --git a/src/core.ts b/src/core.ts index a6730ea..848d371 100644 --- a/src/core.ts +++ b/src/core.ts @@ -30,3 +30,7 @@ export const id: L<(v: T) => T> = _(v => v); export const cnst: L<(v: T) => L<(_: unknown) => T>> = _(v => _(_ => v)) as L<(v: T) => L<(_: unknown) => T>>; +export const pipe: L<(f: L<(v: B) => C>) => L<(g: L<(v: A) => B>) => L<(v: A) => C>>> + = _((f: L<(v: B) => C>) => + _((g: L<(v: A) => B>) => + _((v: A) => f(g(v))))); diff --git a/src/list.ts b/src/list.ts index 150fcfc..4f32af1 100644 --- a/src/list.ts +++ b/src/list.ts @@ -1,4 +1,4 @@ -import { toNative as $$, L, P, _, fromNative as __, ___, cnst, id, undef } from './core'; +import { toNative as $$, L, P, _, fromNative as __, ___, cnst, id, pipe, undef } from './core'; import { EQ, GT, LT, Ord, eq as eqc } from './ord'; import { Bool, False, True, and, iif, or } from './bool'; import { Num, Zero, succ } from './num'; @@ -23,13 +23,16 @@ export const nul: L<(xs: List) => Bool> = _(xs => xs(True)(cnst(cnst(False)))); export const len: L<(xs: List) => Num> - = _(xs => xs(Zero)(_(_x => _(xs => succ(len(xs)))))); + = _(xs => xs(Zero)(cnst(pipe(succ)(len)))); + +export const singleton: L<(v: T) => List> + = _(x => cons(x)(Nil)); export const append: L<(l: List) => L<(r: List) => List>> = _(l => _(r => l(r)(_(x => _(xs => cons(x)(append(xs)(r))))))); export const concat: L<(ls: List>) => List> - = _(ls => ls(Nil)(_(x => _(xs => append(x)(concat(xs)))))); + = _(ls => ls(Nil)(_(x => pipe(append(x))(concat)))); export const repeat: L<(x: T) => List> = _(x => cons(x)(repeat(x))); @@ -46,7 +49,7 @@ export const tail: L<(xs: List) => List> export const foldl: L<(f: L<(a: R) => L<(x: T) => R>>) => L<(z: R) => L<(xs: List) => R>>> = _((f: L<(a: R) => L<(x: T) => R>>) => _((z: R) => - _((xs: List) => xs(z)(_(x => foldl(f)(f(z)(x))))))); + _((xs: List) => xs(z)(pipe(foldl(f))(f(z)))))); export const foldlz: L<(f: L<(a: T) => L<(x: T) => T>>) => L<(xs: List) => T>> = _((f: L<(a: T) => L<(x: T) => T>>) => _((xs: List) => xs(undef)(foldl(f)))); @@ -54,7 +57,7 @@ export const foldlz: L<(f: L<(a: T) => L<(x: T) => T>>) => L<(xs: L export const foldr: L<(f: L<(x: T) => L<(a: R) => R>>) => L<(z: R) => L<(xs: List) => R>>> = _((f: L<(x: T) => L<(a: R) => R>>) => _((z: R) => - _((xs: List) => xs(z)(_(x => _(xs => f(x)(foldr(f)(z)(xs)))))))); + _((xs: List) => xs(z)(_(x => pipe(f(x))(foldr(f)(z))))))); export const foldrz: L<(f: L<(x: T) => L<(a: T) => T>>) => L<(xs: List) => T>> = undef; @@ -102,19 +105,19 @@ export const gt: L<(ecmp: L<(l: T) => L <(r: T) => Ord>>) => L<(l: export const map: L<(f: L<(x: T) => R>) => L<(xs: List) => List>> = _((f: L<(x: T) => R>) => - _((xs: List) => xs(Nil)(_(x => _(xs => cons(f(x))(map(f)(xs))))))); + _((xs: List) => xs(Nil)(_(x => pipe(cons(f(x)))(map(f)))))); export const filter: L<(f: L<(x: T) => Bool>) => L<(xs: List) => List>> = _((f: L<(x: T) => Bool>) => - _((xs: List) => xs(Nil)(_(x => _(xs => iif(f(x))(cons(x))(id)(filter(f)(xs))))))); + _((xs: List) => xs(Nil)(_(x => pipe(iif(f(x))(cons(x))(id))(filter(f)))))); export const any: L<(f: L<(x: T) => Bool>) => L<(xs: List) => Bool>> = _((f: L<(x: T) => Bool>) => - _((xs: List) => xs(False)(_(x => _(xs => or(f(x))(any(f)(xs))))))); + _((xs: List) => xs(False)(_(x => pipe(or(f(x)))(any(f)))))); export const all: L<(f: L<(x: T) => Bool>) => L<(xs: List) => Bool>> = _((f: L<(x: T) => Bool>) => - _((xs: List) => xs(True)(_(x => _(xs => and(f(x))(all(f)(xs))))))); + _((xs: List) => xs(True)(_(x => pipe(and(f(x)))(all(f)))))); export const get: L<(i: Num) => L<(xs: List) => T>> = _(i => _(xs => xs(undef)(_(x => i(cnst(x))(get))))); @@ -126,7 +129,7 @@ export const update: L<(f: L< (p: T) => T>) => L<(i: Num) => L<(xs: xs(undef)(_(x => _(xs => i(cons(f(x))(xs))(_(pi => cons(x)(update(f)(pi)(xs)))))))))); export const set: L<(v: T) => L<(i: Num) => L<(xs: List) => List>>> - = _(v => update(cnst(v))); + = pipe(update)(cnst); export const intersperse: L<(v: T) => L<(xs: List) => List>> = _(v => _(xs => xs(xs)(_(x => _(rxs => rxs(xs)(cnst(cnst(cons(x)(cons(v)(intersperse(v)(rxs))))))))))); diff --git a/src/num.ts b/src/num.ts index f753a3f..5201402 100644 --- a/src/num.ts +++ b/src/num.ts @@ -1,4 +1,4 @@ -import { toNative as $$, L, P, _, fromNative as __, ___, cnst, id } from './core'; +import { toNative as $$, L, P, _, fromNative as __, ___, cnst, id, pipe } from './core'; import { EQ, GT, LT, Ord } from './ord'; import { Bool, False, True, iif } from './bool'; import { Empty, String, append, cons } from './string'; @@ -21,7 +21,7 @@ export const pred: L<(n: Num) => Num> = _(n => n(Zero)(id)); export const cmp: L<(l: Num) => L<(r: Num) => Ord>> - = _(l => _(r => l(r(EQ)(cnst(LT)))(_(pl => r(GT)(cmp(pl)))))); + = _(l => _(r => l(r(EQ)(cnst(LT)))(pipe(r(GT))(cmp)))); export const lt: L<(l: Num) => L<(r: Num) => Bool>> = _(l => _(r => r(False)(l(cnst(True))(lt)))); diff --git a/test/core.spec.ts b/test/core.spec.ts index 7f3e561..b16b9ec 100644 --- a/test/core.spec.ts +++ b/test/core.spec.ts @@ -16,3 +16,9 @@ describe('cnst', () => { expect($$(cnst(__('first'))(undef))).toBe('first'); }); }); + +describe('pipe', () => { + it.failing('applies both functions in order', () => { + expect('Not implemented').toBe('Implemented'); + }); +}); diff --git a/test/list.spec.ts b/test/list.spec.ts index edcb4fe..632dacd 100644 --- a/test/list.spec.ts +++ b/test/list.spec.ts @@ -4,7 +4,7 @@ import { toNOrd as $o, NOrd } from '../src/ord'; import { toBoolean as $b, iif } from '../src/bool'; import { toNumber as $n, toNumber as $nn, Num, Succ, Zero, fromNumber as _n, fromNumber as _nn, cmp as cmpn, eq as eqn, even, gt as ngt, show as nshow, odd, succ, sum } from '../src/num'; import { toChar as $c } from '../src/char'; -import { toArray as $a, Cons, List, Nil, fromArray as _a, all, any, append, cmp, concat, cons, eq, filter, foldl, foldlz, foldr, foldrz, ge, get, gt, head, intersperse, iterate, le, len, lt, map, nul, set, show, snoc, tail, update } from '../src/list'; +import { toArray as $a, Cons, List, Nil, fromArray as _a, all, any, append, cmp, concat, cons, eq, filter, foldl, foldlz, foldr, foldrz, ge, get, gt, head, intersperse, iterate, le, len, lt, map, nul, set, show, singleton, snoc, tail, update } from '../src/list'; import { toString as $s } from '../src/string'; describe('List', () => { @@ -114,6 +114,16 @@ describe('List', () => { it('handles infinite lists', () => { expect($b(ngt(len(infinite))(Zero))).toEqual(true); }); + + it('ignores items', () => { + expect($n(len(cons(undef)(cons(undef)(Nil))))).toEqual(2); + }); + }); + + describe('singleton', () => { + it('singleton 0 is [0]', () => { + expect($na(singleton(_n(0)))).toEqual([0]); + }); }); describe('append', () => {