diff --git a/eslint.config.mjs b/eslint.config.mjs index fae0980..95e0c11 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -32,6 +32,7 @@ export default [ '@stylistic/quotes': ['error', 'single'], '@stylistic/semi': ['error', 'always'], '@stylistic/indent': 'error', + '@stylistic/arrow-parens': ['error', 'as-needed', { requireForBlockBody: false }], '@typescript-eslint/no-unused-vars': [ 'error', { diff --git a/src/bool.ts b/src/bool.ts index 525187a..63229fc 100644 --- a/src/bool.ts +++ b/src/bool.ts @@ -1,5 +1,6 @@ import { toNative as $$, L, P, _, fromNative as __ } from './core'; import { EQ, GT, LT, Ord } from './ord'; +import { String, fromString as _s } from './string'; export type Bool = L<(t: T) => L<(f: T) => T>>; @@ -42,6 +43,9 @@ export const or: L<(l: Bool) => L<(r: Bool) => Bool>> export const xor: L<(l: Bool) => L<(r: Bool) => Bool>> = _(l => _(r => l._(not._(r))._(r))); +export const show: L<(b: Bool) => String> + = _(b => iif._(b)._(_s('True'))._(_s('False'))); + export const fromBoolean: (b: boolean) => Bool = b => b ? True : False; diff --git a/src/char.ts b/src/char.ts index 8d65768..92f63f8 100644 --- a/src/char.ts +++ b/src/char.ts @@ -1,30 +1,16 @@ import { L, _ } from './core'; -import { Bool } from './bool'; -import { toNumber as $n, Num, Zero, fromNumber as _n, cmp as cmpn, eq as eqn, ge as gen, gt as gtn, le as len, lt as ltn } from './num'; -import { Ord } from 'src/ord'; +import { toNumber as $n, Byte, fromNumber as _n, x00 } from './byte'; +import { Empty, String, cons } from './string'; -export type Char = Num; +export type Char = Byte; export const Null: Char - = Zero; + = x00; -export const cmp: L<(l: Char) => L<(r: Char) => Ord>> - = cmpn; +export { inc, dec, ifz as ifn, cmp, lt, le, eq, ge, gt } from './byte'; -export const lt: L<(l: Char) => L<(r: Char) => Bool>> - = ltn; - -export const le: L<(l: Char) => L<(r: Char) => Bool>> - = len; - -export const eq: L<(l: Char) => L<(r: Char) => Bool>> - = eqn; - -export const ge: L<(l: Char) => L<(r: Char) => Bool>> - = gen; - -export const gt: L<(l: Char) => L<(r: Char) => Bool>> - = gtn; +export const show: L<(c: Char) => String> + = _(c => cons._(fromChar('\''))._(cons._(c)._(cons._(fromChar('\''))._(Empty)))); export const fromChar: (c: string) => Char = c => _n(c.charCodeAt(0)); diff --git a/src/debug.ts b/src/debug.ts new file mode 100644 index 0000000..4eed77d --- /dev/null +++ b/src/debug.ts @@ -0,0 +1,8 @@ +import { L, P, _ } from './core'; +import { String, toString } from './string'; + +export const log: L<(s: String) => L<(p: T) => T>> + = _(s => _(p => { + console.log(toString(s)); + return p; + })); diff --git a/src/list.ts b/src/list.ts index 764858f..c86f3c0 100644 --- a/src/list.ts +++ b/src/list.ts @@ -1,7 +1,8 @@ import { toNative as $$, L, P, _, fromNative as __, undef } from './core'; import { EQ, GT, LT, Ord, eq as eqc } from './ord'; import { Bool, False, True, and, iif, or } from './bool'; -import { Num } from 'src/num'; +import { Num, Zero, succ } from './num'; +import { String, fromString as _s } from './string'; export type List = L<(z: R) => L<(f: L<(x: T) => L<(xs: List) => R>>) => R>>; @@ -14,8 +15,21 @@ export const Cons: L<(x: T) => L<(xs: List) => List>> export const cons: L<(x: T) => L<(xs: List) => List>> = Cons; -export const concat: L<(l: List) => L<(r: List) => List>> - = _(l => _(r => l._(r)._(_(x => _(xs => cons._(x)._(concat._(xs)._(r))))))); +export const snoc: L<(xs: List) => L<(x: T) => List>> + = _((xs: List) => + _((x: T) => xs._(cons._(x)._(Nil))._(_(y => _(ys => cons._(y)._(snoc._(ys)._(x))))))); + +export const nul: L<(xs: List) => Bool> + = _(xs => xs._(True)._(_(_x => _(_xs => False)))); + +export const len: L<(xs: List) => Num> + = _(xs => xs._(Zero)._(_(_x => _(xs => succ._(len._(xs)))))); + +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)))))); export const head: L<(xs: List) => T> = _(xs => xs._(undef)._(_(x => _(_xs => x)))); @@ -114,6 +128,14 @@ export const update: L<(f: L< (p: T) => T>) => L<(i: Num) => L<(xs: export const set: L<(v: T) => L<(i: Num) => L<(xs: List) => List>>> = _((v: T) => update._(_(_ => v))); +export const intersperse: L<(v: T) => L<(xs: List) => List>> + = _(v => _(xs => + xs._(xs)._(_(x => _(rxs => rxs._(xs)._(_(_rx => _(_rrxs => cons._(x)._(cons._(v)._(intersperse._(v)._(rxs))))))))))); + +export const show: L<(eshow: L<(e: T) => String>) => L<(xs: List) => String>> + = _(eshow => _(xs => + concat._(snoc._(cons._(_s('['))._(intersperse._(_s(', '))._(map._(eshow)._(xs))))._(_s(']'))))); + export const fromArray: (xs: T[]) => List = xs => xs.length === 0 ? Nil : Cons._(xs[0])._(new L(() => fromArray(xs.slice(1)).value)); diff --git a/src/num.ts b/src/num.ts index a344ea4..c60b4fa 100644 --- a/src/num.ts +++ b/src/num.ts @@ -1,6 +1,7 @@ import { toNative as $$, L, P, _, fromNative as __, id } from './core'; import { EQ, GT, LT, Ord } from './ord'; -import { Bool, False, iif, True } from './bool'; +import { Bool, False, True, iif } from './bool'; +import { Empty, String, append, cons } from './string'; export type Num = L<(z: T) => L<(n: L<(p: Num) => T>) => T>>; @@ -58,6 +59,11 @@ export const div: L<(l: Num) => L<(r: Num) => Num>> export const mod: L<(l: Num) => L<(r: Num) => Num>> = _(l => _(r => iif._(lt._(l)._(r))._(l)._(mod._(sub._(l)._(r))._(r)))); +export const show: L<(n: Num) => String> + = _(n => iif._(lt._(n)._(fromNumber(10))) + ._(cons._(sum._(n)._(fromNumber(48)))._(Empty)) + ._(append._(show._(div._(n)._(fromNumber(10))))._(show._(mod._(n)._(fromNumber(10)))))); + export const fromNumber: (n: number) => Num = n => !n ? Zero : Succ._(new L(() => fromNumber(n - 1).value)); diff --git a/src/ord.ts b/src/ord.ts index 6212096..8a04afa 100644 --- a/src/ord.ts +++ b/src/ord.ts @@ -1,5 +1,6 @@ import { toNative as $$, L, P, _, fromNative as __ } from './core'; import { Bool, False, True } from './bool'; +import { String, fromString as _s } from './string'; export type Ord = L<(lt: T) => L<(eq: T) => L<(gt: T) => T>>>; @@ -24,6 +25,9 @@ export const eq: L<(l: Ord) => L<(r: Ord) => Bool>> ._(r._(False)._(True)._(False)) ._(r._(False)._(False)._(True)))); +export const show: L<(o: Ord) => String> + = _(o => o._(_s('LT'))._(_s('EQ'))._(_s('GT'))); + export const fromNOrd: (b: NOrd) => Ord = o => o === NOrd.LT ? LT : o === NOrd.EQ ? EQ : GT; diff --git a/src/pair.ts b/src/pair.ts index a027da6..38c2c34 100644 --- a/src/pair.ts +++ b/src/pair.ts @@ -1,6 +1,8 @@ import { L, P, _ } from './core'; import { GT, LT, Ord } from './ord'; import { Bool, False, True, and } from './bool'; +import { Nil, concat, cons } from './list'; +import { String, fromString as _s } from './string'; export type Pair = L<(f: L<(f: F) => L<(s: S) => R>>) => R>; @@ -73,3 +75,9 @@ export const gt: L<(fcmp: L<(l: F) => L<(r: F) => Ord> _((l: Pair) => _((r: Pair) => fcmp._(fst._(l))._(fst._(r))._(False)._(scmp._(snd._(l))._(snd._(r))._(False)._(False)._(True))._(True))))); + +export const show: L<(fshow: L<(f: F) => String>) => L<(sshow: L<(s: S) => String>) => L<(p: Pair) => String>>> + = _((fshow: L<(f: F) => String>) => + _((sshow: L<(s: S) => String>) => + _((p: Pair) => + uncurry._(_(f => _(s => concat._(cons._(_s('('))._(cons._(fshow._(f))._(cons._(_s(', '))._(cons._(sshow._(s))._(cons._(_s(')'))._(Nil)))))))))._(p)))); diff --git a/src/string.ts b/src/string.ts index 13159eb..3664845 100644 --- a/src/string.ts +++ b/src/string.ts @@ -3,21 +3,11 @@ import { Ord } from './ord'; import { Bool } from './bool'; import { fromNumber as _nn } from './num'; import { toChar as $c, Char, fromChar as _c, cmp as cmpc, eq as eqc } from './char'; -import { Cons as ConsL, List, Nil, cmp as cmpl, concat as concatl, eq as eql, ge as gel, gt as gtl, le as lel, lt as ltl } from './list'; +import { Cons, List, Nil, cmp as cmpl, concat, cons, eq as eql, ge as gel, gt as gtl, le as lel, lt as ltl } from './list'; export type String = List; -export const Empty: String - = Nil; - -export const Cons: L<(c: Char) => L<(s: String) => String>> - = ConsL; - -export const cons: L<(c: Char) => L<(s: String) => String>> - = Cons; - -export const concat: L<(l: String) => L<(r: String) => String>> - = concatl; +export { Nil as Empty, nul as empty, len, Cons, cons, snoc, append, get, update, set } from './list'; export const cmp: L<(l: String) => L<(r: String) => Ord>> = cmpl._(cmpc); @@ -37,6 +27,9 @@ export const ge: L<(l: String) => L<(r: String) => Bool>> export const gt: L<(l: String) => L<(r: String) => Bool>> = gtl._(cmpc); +export const show: L<(s: String) => String> + = _(s => concat._(cons._(fromString('"'))._(cons._(s)._(cons._(fromString('"'))._(Nil))))); + export const fromString: (xs: string) => String = xs => xs.length === 0 ? Nil : Cons._(_c(xs[0]))._(new L(() => fromString(xs.slice(1)).value)); diff --git a/test/bool.spec.ts b/test/bool.spec.ts index 298e94f..73793ea 100644 --- a/test/bool.spec.ts +++ b/test/bool.spec.ts @@ -1,157 +1,158 @@ import { describe, expect, it } from '@jest/globals'; import { undef } from '../src/core'; import { toNOrd as $o, NOrd } from '../src/ord'; -import { toBoolean as $, False, True, fromBoolean as _, and, cmp, eq, ge, gt, iif, le, lt, not, or, xor } from '../src/bool'; +import { toBoolean as $b, False, True, fromBoolean as _b, and, cmp, eq, ge, gt, iif, le, lt, not, or, show, xor } from '../src/bool'; +import { toString as $s } from '../src/string'; describe('Bool', () => { describe('toBoolean', () => { it('converts True', () => { - expect($(True)).toBe(true); + expect($b(True)).toBe(true); }); it('converts False', () => { - expect($(False)).toBe(false); + expect($b(False)).toBe(false); }); }); describe('fromBoolean', () => { it('converts true', () => { - expect($(_(true))).toBe(true); + expect($b(_b(true))).toBe(true); }); it('converts false', () => { - expect($(_(false))).toBe(false); + expect($b(_b(false))).toBe(false); }); }); describe('iif', () => { it('returns true argument', () => { - expect($(iif._(True)._(True)._(False))).toBe(true); + expect($b(iif._(True)._(True)._(False))).toBe(true); }); it('returns false argument', () => { - expect($(iif._(False)._(True)._(False))).toBe(false); + expect($b(iif._(False)._(True)._(False))).toBe(false); }); it('ignores other argument', () => { - expect($(iif._(True)._(True)._(undef))).toBe(true); - expect($(iif._(False)._(undef)._(False))).toBe(false); + expect($b(iif._(True)._(True)._(undef))).toBe(true); + expect($b(iif._(False)._(undef)._(False))).toBe(false); }); }); describe('not', () => { it('not False is True', () => { - expect($(not._(False))).toBe(true); + expect($b(not._(False))).toBe(true); }); it('not True is False', () => { - expect($(not._(True))).toBe(false); + expect($b(not._(True))).toBe(false); }); }); describe('lt', () => { it('False lt False is False', () => { - expect($(lt._(False)._(False))).toBe(false); + expect($b(lt._(False)._(False))).toBe(false); }); it('False lt True is True', () => { - expect($(lt._(False)._(True))).toBe(true); + expect($b(lt._(False)._(True))).toBe(true); }); it('True lt False is False', () => { - expect($(lt._(True)._(False))).toBe(false); + expect($b(lt._(True)._(False))).toBe(false); }); it('True lt True is False', () => { - expect($(lt._(True)._(True))).toBe(false); + expect($b(lt._(True)._(True))).toBe(false); }); it('True lt ignores second argument', () => { - expect($(lt._(True)._(undef))).toBe(false); + expect($b(lt._(True)._(undef))).toBe(false); }); }); describe('le', () => { it('False le False is True', () => { - expect($(le._(False)._(False))).toBe(true); + expect($b(le._(False)._(False))).toBe(true); }); it('False le True is True', () => { - expect($(le._(False)._(True))).toBe(true); + expect($b(le._(False)._(True))).toBe(true); }); it('True le False is False', () => { - expect($(le._(True)._(False))).toBe(false); + expect($b(le._(True)._(False))).toBe(false); }); it('True le True is True', () => { - expect($(le._(True)._(True))).toBe(true); + expect($b(le._(True)._(True))).toBe(true); }); it('False le ignores second argument', () => { - expect($(le._(False)._(undef))).toBe(true); + expect($b(le._(False)._(undef))).toBe(true); }); }); describe('eq', () => { it('False eq False is True', () => { - expect($(eq._(False)._(False))).toBe(true); + expect($b(eq._(False)._(False))).toBe(true); }); it('False eq True is False', () => { - expect($(eq._(False)._(True))).toBe(false); + expect($b(eq._(False)._(True))).toBe(false); }); it('True eq False is False', () => { - expect($(eq._(True)._(False))).toBe(false); + expect($b(eq._(True)._(False))).toBe(false); }); it('True eq True is True', () => { - expect($(eq._(True)._(True))).toBe(true); + expect($b(eq._(True)._(True))).toBe(true); }); }); describe('ge', () => { it('False ge False is True', () => { - expect($(ge._(False)._(False))).toBe(true); + expect($b(ge._(False)._(False))).toBe(true); }); it('False ge True is False', () => { - expect($(ge._(False)._(True))).toBe(false); + expect($b(ge._(False)._(True))).toBe(false); }); it('True ge False is True', () => { - expect($(ge._(True)._(False))).toBe(true); + expect($b(ge._(True)._(False))).toBe(true); }); it('True ge True is True', () => { - expect($(ge._(True)._(True))).toBe(true); + expect($b(ge._(True)._(True))).toBe(true); }); it('True ge ignores second argument', () => { - expect($(ge._(True)._(undef))).toBe(true); + expect($b(ge._(True)._(undef))).toBe(true); }); }); describe('gt', () => { it('False gt False is False', () => { - expect($(gt._(False)._(False))).toBe(false); + expect($b(gt._(False)._(False))).toBe(false); }); it('False gt True is False', () => { - expect($(gt._(False)._(True))).toBe(false); + expect($b(gt._(False)._(True))).toBe(false); }); it('True gt False is True', () => { - expect($(gt._(True)._(False))).toBe(true); + expect($b(gt._(True)._(False))).toBe(true); }); it('True gt True is False', () => { - expect($(gt._(True)._(True))).toBe(false); + expect($b(gt._(True)._(True))).toBe(false); }); it('False gt ignores second argument', () => { - expect($(gt._(False)._(undef))).toBe(false); + expect($b(gt._(False)._(undef))).toBe(false); }); }); @@ -175,63 +176,73 @@ describe('Bool', () => { describe('and', () => { it('False and False is False', () => { - expect($(and._(False)._(False))).toBe(false); + expect($b(and._(False)._(False))).toBe(false); }); it('False and True is False', () => { - expect($(and._(False)._(True))).toBe(false); + expect($b(and._(False)._(True))).toBe(false); }); it('True and False is False', () => { - expect($(and._(True)._(False))).toBe(false); + expect($b(and._(True)._(False))).toBe(false); }); it('True and True is True', () => { - expect($(and._(True)._(True))).toBe(true); + expect($b(and._(True)._(True))).toBe(true); }); it('False and ignores other argument', () => { - expect($(and._(False)._(undef))).toBe(false); + expect($b(and._(False)._(undef))).toBe(false); }); }); describe('or', () => { it('False or False is False', () => { - expect($(or._(False)._(False))).toBe(false); + expect($b(or._(False)._(False))).toBe(false); }); it('False or True is True', () => { - expect($(or._(False)._(True))).toBe(true); + expect($b(or._(False)._(True))).toBe(true); }); it('True or False is True', () => { - expect($(or._(True)._(False))).toBe(true); + expect($b(or._(True)._(False))).toBe(true); }); it('True or True is True', () => { - expect($(or._(True)._(True))).toBe(true); + expect($b(or._(True)._(True))).toBe(true); }); it('True or ignores other argument', () => { - expect($(or._(True)._(undef))).toBe(true); + expect($b(or._(True)._(undef))).toBe(true); }); }); describe('xor', () => { it('False xor False is False', () => { - expect($(xor._(False)._(False))).toBe(false); + expect($b(xor._(False)._(False))).toBe(false); }); it('False xor True is True', () => { - expect($(xor._(False)._(True))).toBe(true); + expect($b(xor._(False)._(True))).toBe(true); }); it('True xor False is True', () => { - expect($(xor._(True)._(False))).toBe(true); + expect($b(xor._(True)._(False))).toBe(true); }); it('True xor True is False', () => { - expect($(xor._(True)._(True))).toBe(false); + expect($b(xor._(True)._(True))).toBe(false); + }); + }); + + describe('show', () => { + it('show False is "False"', () => { + expect($s(show._(False))).toBe('False'); + }); + + it('show True is "True"', () => { + expect($s(show._(True))).toBe('True'); }); }); }); diff --git a/test/char.spec.ts b/test/char.spec.ts index 8779e59..ef7d484 100644 --- a/test/char.spec.ts +++ b/test/char.spec.ts @@ -1,199 +1,214 @@ import { describe, expect, it } from '@jest/globals'; import { toNOrd as $o, NOrd } from '../src/ord'; import { toBoolean as $b, fromBoolean as _b } from '../src/bool'; -import { fromNumber as _n } from '../src/num'; -import { toChar as $, fromChar as _, cmp, eq, ge, gt, le, lt } from '../src/char'; +import { fromNumber as _n } from '../src/byte'; +import { toChar as $c, fromChar as _c, cmp, eq, ge, gt, le, lt, show } from '../src/char'; +import { toString as $s } from '../src/string'; describe('Char', () => { describe('toChar', () => { it('converts "0"', () => { - expect($(_n(48))).toBe('0'); + expect($c(_n(48))).toBe('0'); }); it('converts "a"', () => { - expect($(_n(97))).toBe('a'); + expect($c(_n(97))).toBe('a'); }); it('converts "Z"', () => { - expect($(_n(90))).toBe('Z'); + expect($c(_n(90))).toBe('Z'); }); it('converts "-"', () => { - expect($(_n(45))).toBe('-'); + expect($c(_n(45))).toBe('-'); }); }); describe('fromChar', () => { it('converts "0"', () => { - expect($(_('0'))).toBe('0'); + expect($c(_c('0'))).toBe('0'); }); it('converts "a"', () => { - expect($(_('a'))).toBe('a'); + expect($c(_c('a'))).toBe('a'); }); it('converts "Z"', () => { - expect($(_('Z'))).toBe('Z'); + expect($c(_c('Z'))).toBe('Z'); }); it('converts "-"', () => { - expect($(_('-'))).toBe('-'); + expect($c(_c('-'))).toBe('-'); }); }); describe('cmp', () => { it('"0" cmp "0" is EQ', () => { - expect($o(cmp._(_('0'))._(_('0')))).toBe(NOrd.EQ); + expect($o(cmp._(_c('0'))._(_c('0')))).toBe(NOrd.EQ); }); it('"0" cmp "a" is LT', () => { - expect($o(cmp._(_('0'))._(_('a')))).toBe(NOrd.LT); + expect($o(cmp._(_c('0'))._(_c('a')))).toBe(NOrd.LT); }); it('"a" cmp "0" is GT', () => { - expect($o(cmp._(_('a'))._(_('0')))).toBe(NOrd.GT); + expect($o(cmp._(_c('a'))._(_c('0')))).toBe(NOrd.GT); }); it('"z" cmp "z" is EQ', () => { - expect($o(cmp._(_('z'))._(_('z')))).toBe(NOrd.EQ); + expect($o(cmp._(_c('z'))._(_c('z')))).toBe(NOrd.EQ); }); it('"z" cmp "-" is GT', () => { - expect($o(cmp._(_('z'))._(_('-')))).toBe(NOrd.GT); + expect($o(cmp._(_c('z'))._(_c('-')))).toBe(NOrd.GT); }); it('"-" cmp "z" is LT', () => { - expect($o(cmp._(_('-'))._(_('z')))).toBe(NOrd.LT); + expect($o(cmp._(_c('-'))._(_c('z')))).toBe(NOrd.LT); }); }); describe('lt', () => { it('"0" lt "0" is False', () => { - expect($b(lt._(_('0'))._(_('0')))).toBe(false); + expect($b(lt._(_c('0'))._(_c('0')))).toBe(false); }); it('"0" lt "a" is True', () => { - expect($b(lt._(_('0'))._(_('a')))).toBe(true); + expect($b(lt._(_c('0'))._(_c('a')))).toBe(true); }); it('"a" lt "0" is False', () => { - expect($b(lt._(_('a'))._(_('0')))).toBe(false); + expect($b(lt._(_c('a'))._(_c('0')))).toBe(false); }); it('"z" lt "z" is False', () => { - expect($b(lt._(_('z'))._(_('z')))).toBe(false); + expect($b(lt._(_c('z'))._(_c('z')))).toBe(false); }); it('"z" lt "-" is False', () => { - expect($b(lt._(_('z'))._(_('-')))).toBe(false); + expect($b(lt._(_c('z'))._(_c('-')))).toBe(false); }); it('"-" lt "z" is True', () => { - expect($b(lt._(_('-'))._(_('z')))).toBe(true); + expect($b(lt._(_c('-'))._(_c('z')))).toBe(true); }); }); describe('le', () => { it('"0" le "0" is True', () => { - expect($b(le._(_('0'))._(_('0')))).toBe(true); + expect($b(le._(_c('0'))._(_c('0')))).toBe(true); }); it('"0" le "a" is True', () => { - expect($b(le._(_('0'))._(_('a')))).toBe(true); + expect($b(le._(_c('0'))._(_c('a')))).toBe(true); }); it('"a" le "0" is False', () => { - expect($b(le._(_('a'))._(_('0')))).toBe(false); + expect($b(le._(_c('a'))._(_c('0')))).toBe(false); }); it('"z" le "z" is True', () => { - expect($b(le._(_('z'))._(_('z')))).toBe(true); + expect($b(le._(_c('z'))._(_c('z')))).toBe(true); }); it('"z" le "-" is False', () => { - expect($b(le._(_('z'))._(_('-')))).toBe(false); + expect($b(le._(_c('z'))._(_c('-')))).toBe(false); }); it('"-" le "z" is True', () => { - expect($b(le._(_('-'))._(_('z')))).toBe(true); + expect($b(le._(_c('-'))._(_c('z')))).toBe(true); }); }); describe('eq', () => { it('"0" eq "0" is True', () => { - expect($b(eq._(_('0'))._(_('0')))).toBe(true); + expect($b(eq._(_c('0'))._(_c('0')))).toBe(true); }); it('"0" eq "a" is False', () => { - expect($b(eq._(_('0'))._(_('a')))).toBe(false); + expect($b(eq._(_c('0'))._(_c('a')))).toBe(false); }); it('"a" eq "0" is False', () => { - expect($b(eq._(_('a'))._(_('0')))).toBe(false); + expect($b(eq._(_c('a'))._(_c('0')))).toBe(false); }); it('"z" eq "z" is True', () => { - expect($b(eq._(_('z'))._(_('z')))).toBe(true); + expect($b(eq._(_c('z'))._(_c('z')))).toBe(true); }); it('"z" eq "-" is False', () => { - expect($b(eq._(_('z'))._(_('-')))).toBe(false); + expect($b(eq._(_c('z'))._(_c('-')))).toBe(false); }); it('"-" eq "z" is False', () => { - expect($b(eq._(_('-'))._(_('z')))).toBe(false); + expect($b(eq._(_c('-'))._(_c('z')))).toBe(false); }); }); describe('ge', () => { it('"0" ge "0" is True', () => { - expect($b(ge._(_('0'))._(_('0')))).toBe(true); + expect($b(ge._(_c('0'))._(_c('0')))).toBe(true); }); it('"0" ge "a" is False', () => { - expect($b(ge._(_('0'))._(_('a')))).toBe(false); + expect($b(ge._(_c('0'))._(_c('a')))).toBe(false); }); it('"a" ge "0" is True', () => { - expect($b(ge._(_('a'))._(_('0')))).toBe(true); + expect($b(ge._(_c('a'))._(_c('0')))).toBe(true); }); it('"z" ge "z" is True', () => { - expect($b(ge._(_('z'))._(_('z')))).toBe(true); + expect($b(ge._(_c('z'))._(_c('z')))).toBe(true); }); it('"z" ge "-" is True', () => { - expect($b(ge._(_('z'))._(_('-')))).toBe(true); + expect($b(ge._(_c('z'))._(_c('-')))).toBe(true); }); it('"-" ge "z" is False', () => { - expect($b(ge._(_('-'))._(_('z')))).toBe(false); + expect($b(ge._(_c('-'))._(_c('z')))).toBe(false); }); }); describe('gt', () => { it('"0" gt "0" is False', () => { - expect($b(gt._(_('0'))._(_('0')))).toBe(false); + expect($b(gt._(_c('0'))._(_c('0')))).toBe(false); }); it('"0" gt "a" is False', () => { - expect($b(gt._(_('0'))._(_('a')))).toBe(false); + expect($b(gt._(_c('0'))._(_c('a')))).toBe(false); }); it('"a" gt "0" is True', () => { - expect($b(gt._(_('a'))._(_('0')))).toBe(true); + expect($b(gt._(_c('a'))._(_c('0')))).toBe(true); }); it('"z" gt "z" is False', () => { - expect($b(gt._(_('z'))._(_('z')))).toBe(false); + expect($b(gt._(_c('z'))._(_c('z')))).toBe(false); }); it('"z" gt "-" is True', () => { - expect($b(gt._(_('z'))._(_('-')))).toBe(true); + expect($b(gt._(_c('z'))._(_c('-')))).toBe(true); }); it('"-" gt "z" is False', () => { - expect($b(gt._(_('-'))._(_('z')))).toBe(false); + expect($b(gt._(_c('-'))._(_c('z')))).toBe(false); + }); + }); + + describe('show', () => { + it('show "0" is "\'0\'"', () => { + expect($s(show._(_c('0')))).toBe('\'0\''); + }); + + it('show "a" is "\'a\'"', () => { + expect($s(show._(_c('a')))).toBe('\'a\''); + }); + + it('show "-" is "\'-\'"', () => { + expect($s(show._(_c('-')))).toBe('\'-\''); }); }); }); diff --git a/test/list.spec.ts b/test/list.spec.ts index 55ba529..36ff778 100644 --- a/test/list.spec.ts +++ b/test/list.spec.ts @@ -2,8 +2,10 @@ import { describe, expect, it } from '@jest/globals'; import { toNative as $$, L, _, fromNative as __, undef } from '../src/core'; 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, odd, succ, sum } from '../src/num'; -import { toArray as $a, Cons, List, Nil, fromArray as _a, all, any, cmp, concat, cons, eq, filter, foldl, foldlz, foldr, foldrz, ge, get, gt, head, le, lt, map, set, tail, update } from '../src/list'; +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, le, len, lt, map, nul, set, show, snoc, tail, update } from '../src/list'; +import { toString as $s } from '../src/string'; describe('List', () => { const iterate: (n: Num) => List = n => new L(() => Cons._(n)._(iterate(Succ._(n))).value); @@ -61,21 +63,94 @@ describe('List', () => { }); }); + describe('snoc', () => { + it('Nil snoc 0 is [0]', () => { + expect($na(snoc._(Nil)._(_n(0)))).toEqual([0]); + }); + + it('[1] snoc 0 is [1, 0]', () => { + expect($na(snoc._(_na([1]))._(_n(0)))).toEqual([1, 0]); + }); + + it('[1, 2] snoc 0 is [1, 2, 0]', () => { + expect($na(snoc._(_na([1, 2]))._(_n(0)))).toEqual([1, 2, 0]); + }); + + it('handles infinite lists', () => { + expect($n(snoc._(infinite)._(_n(0))._(undef)._(_(x => _(_xs => x))))).toBe(0); + }); + }); + + describe('nul', () => { + it('nul Nil is True', () => { + expect($b(nul._(_na([])))).toEqual(true); + }); + + it('nul [1] is False', () => { + expect($b(nul._(_na([1])))).toEqual(false); + }); + + it('nul [1, 2] is False', () => { + expect($b(nul._(_na([1, 2])))).toEqual(false); + }); + + it('handles infinite lists', () => { + expect($b(nul._(infinite))).toEqual(false); + }); + }); + + describe('len', () => { + it('len Nil is 0', () => { + expect($n(len._(_na([])))).toEqual(0); + }); + + it('len [1] is 1', () => { + expect($n(len._(_na([1])))).toEqual(1); + }); + + it('len [1, 2] is 2', () => { + expect($n(len._(_na([1, 2])))).toEqual(2); + }); + + it('handles infinite lists', () => { + expect($b(ngt._(len._(infinite))._(Zero))).toEqual(true); + }); + }); + + describe('append', () => { + it('Nil append Nil is Nil', () => { + expect($na(append._(Nil)._(Nil))).toEqual([]); + }); + + it('[0] append [1] is [0, 1]', () => { + expect($na(append._(_na([0]))._(_na([1])))).toEqual([0, 1]); + }); + + it('[0, 1] append [2, 3] is [0, 1, 2, 3]', () => { + expect($na(append._(_na([0, 1]))._(_na([2, 3])))).toEqual([0, 1, 2, 3]); + }); + + it('handles infinite lists', () => { + expect($n(append._(infinite)._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe(0); + }); + }); + describe('concat', () => { - it('Nil concat Nil is Nil', () => { - expect($na(concat._(Nil)._(Nil))).toEqual([]); + it('concat [Nil, Nil, Nil] is Nil', () => { + expect($na(concat._(cons._(Nil)._(cons._(Nil)._(cons._(Nil)._(Nil)))))).toEqual([]); }); - it('[0] concat [1] is [0, 1]', () => { - expect($na(concat._(_na([0]))._(_na([1])))).toEqual([0, 1]); + it('concat [[0], [1], [2]] is [0, 1, 2]', () => { + expect($na(concat._(cons._(_na([0]))._(cons._(_na([1]))._(cons._(_na([2]))._(Nil)))))).toEqual([0, 1, 2]); }); - it('[0, 1] concat [2, 3] is [0, 1, 2, 3]', () => { - expect($na(concat._(_na([0, 1]))._(_na([2, 3])))).toEqual([0, 1, 2, 3]); + it('concat [[0, 1], [2, 3], [4, 5]] is [0, 1, 2, 3, 4, 5]', () => { + expect($na(concat._(cons._(_na([0, 1]))._(cons._(_na([2, 3]))._(cons._(_na([4, 5]))._(Nil)))))).toEqual([0, 1, 2, 3, 4, 5]); }); it('handles infinite lists', () => { - expect($n(concat._(infinite)._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe(0); + const dinfinite: List = cons._(infinite)._(new L(() => dinfinite.value)); + expect($n(concat._(dinfinite)._(undef)._(_(x => _(_xs => x))))).toBe(0); }); }); @@ -583,4 +658,40 @@ describe('List', () => { expect($n(get._(_n(4))._(update._(succ)._(_n(4))._(infinite)))).toBe(5); }); }); + + describe('intersperse', () => { + it('0 intersperse Nil is Nil', () => { + expect($na(intersperse._(_n(0))._(Nil))).toEqual([]); + }); + + it('0 intersperse [1] is [1]', () => { + expect($na(intersperse._(_n(0))._(_na([1])))).toEqual([1]); + }); + + it('0 intersperse [1, 2, 3] is [1, 0, 2, 0, 3]', () => { + expect($na(intersperse._(_n(0))._(_na([1, 2, 3])))).toEqual([1, 0, 2, 0, 3]); + }); + + it('handles infinite lists', () => { + expect($n(head._(intersperse._(_n(0))._(infinite)))).toBe(0); + }); + }); + + describe('show', () => { + it('show Nil is "[]"', () => { + expect($s(show._(nshow)._(_na([])))).toBe('[]'); + }); + + it('show [0] is "[0]"', () => { + expect($s(show._(nshow)._(_na([0])))).toBe('[0]'); + }); + + it('show [0, 1, 2] is "[0, 1, 2]"', () => { + expect($s(show._(nshow)._(_na([0, 1, 2])))).toBe('[0, 1, 2]'); + }); + + it('handles infinite lists', () => { + expect($c(head._(show._(nshow)._(infinite)))).toBe('['); + }); + }); }); diff --git a/test/num.spec.ts b/test/num.spec.ts index 40d72a8..de4b658 100644 --- a/test/num.spec.ts +++ b/test/num.spec.ts @@ -2,50 +2,51 @@ import { describe, expect, it } from '@jest/globals'; import { L, undef } from '../src/core'; import { toNOrd as $o, NOrd } from '../src/ord'; import { toBoolean as $b, fromBoolean as _b } from '../src/bool'; -import { toNumber as $, Num, Succ, Zero, fromNumber as _, cmp, div, eq, ge, gt, ifz, le, lt, mod, mul, pred, sub, succ, sum } from '../src/num'; +import { toNumber as $n, Num, Succ, Zero, fromNumber as _n, cmp, div, eq, ge, gt, ifz, le, lt, mod, mul, pred, show, sub, succ, sum } from '../src/num'; +import { toString as $s } from '../src/string'; describe('Num', () => { const infinity: Num = new L(() => Succ._(infinity).value); describe('toNumber', () => { it('converts 0', () => { - expect($(Zero)).toBe(0); + expect($n(Zero)).toBe(0); }); it('converts 1', () => { - expect($(Succ._(Zero))).toBe(1); + expect($n(Succ._(Zero))).toBe(1); }); it('converts 2', () => { - expect($(Succ._(Succ._(Zero)))).toBe(2); + expect($n(Succ._(Succ._(Zero)))).toBe(2); }); }); describe('fromNumber', () => { it('converts 0', () => { - expect($(_(0))).toBe(0); + expect($n(_n(0))).toBe(0); }); it('converts 1', () => { - expect($(_(1))).toBe(1); + expect($n(_n(1))).toBe(1); }); it('converts 2', () => { - expect($(_(2))).toBe(2); + expect($n(_n(2))).toBe(2); }); }); describe('ifz', () => { it('returns zero branch', () => { - expect($b(ifz._(_(0))._(_b(true))._(_b(false)))).toBe(true); + expect($b(ifz._(_n(0))._(_b(true))._(_b(false)))).toBe(true); }); it('returns non-zero branch', () => { - expect($b(ifz._(_(1))._(_b(true))._(_b(false)))).toBe(false); + expect($b(ifz._(_n(1))._(_b(true))._(_b(false)))).toBe(false); }); it('returns non-zero branch', () => { - expect($b(ifz._(_(10))._(_b(true))._(_b(false)))).toBe(false); + expect($b(ifz._(_n(10))._(_b(true))._(_b(false)))).toBe(false); }); it('handles infinity', () => { @@ -55,333 +56,351 @@ describe('Num', () => { describe('succ', () => { it('succ 0 is 1', () => { - expect($(succ._(_(0)))).toBe(1); + expect($n(succ._(_n(0)))).toBe(1); }); it('succ 1 is 2', () => { - expect($(succ._(_(1)))).toBe(2); + expect($n(succ._(_n(1)))).toBe(2); }); it('succ 10 is 11', () => { - expect($(succ._(_(10)))).toBe(11); + expect($n(succ._(_n(10)))).toBe(11); }); }); describe('pred', () => { it('pred 0 is 0', () => { - expect($(pred._(_(0)))).toBe(0); + expect($n(pred._(_n(0)))).toBe(0); }); it('pred 1 is 0', () => { - expect($(pred._(_(1)))).toBe(0); + expect($n(pred._(_n(1)))).toBe(0); }); it('pred 10 is 9', () => { - expect($(pred._(_(10)))).toBe(9); + expect($n(pred._(_n(10)))).toBe(9); }); }); describe('cmp', () => { it('0 cmp 0 is EQ', () => { - expect($o(cmp._(_(0))._(_(0)))).toBe(NOrd.EQ); + expect($o(cmp._(_n(0))._(_n(0)))).toBe(NOrd.EQ); }); it('0 cmp 1 is LT', () => { - expect($o(cmp._(_(0))._(_(1)))).toBe(NOrd.LT); + expect($o(cmp._(_n(0))._(_n(1)))).toBe(NOrd.LT); }); it('1 cmp 0 is GT', () => { - expect($o(cmp._(_(1))._(_(0)))).toBe(NOrd.GT); + expect($o(cmp._(_n(1))._(_n(0)))).toBe(NOrd.GT); }); it('3 cmp 3 is EQ', () => { - expect($o(cmp._(_(3))._(_(3)))).toBe(NOrd.EQ); + expect($o(cmp._(_n(3))._(_n(3)))).toBe(NOrd.EQ); }); it('3 cmp 7 is LT', () => { - expect($o(cmp._(_(3))._(_(7)))).toBe(NOrd.LT); + expect($o(cmp._(_n(3))._(_n(7)))).toBe(NOrd.LT); }); it('7 cmp 3 is GT', () => { - expect($o(cmp._(_(7))._(_(3)))).toBe(NOrd.GT); + expect($o(cmp._(_n(7))._(_n(3)))).toBe(NOrd.GT); }); it('handles infinity', () => { - expect($o(cmp._(_(7))._(infinity))).toBe(NOrd.LT); - expect($o(cmp._(infinity)._(_(7)))).toBe(NOrd.GT); + expect($o(cmp._(_n(7))._(infinity))).toBe(NOrd.LT); + expect($o(cmp._(infinity)._(_n(7)))).toBe(NOrd.GT); }); }); describe('lt', () => { it('0 lt 0 is False', () => { - expect($b(lt._(_(0))._(_(0)))).toBe(false); + expect($b(lt._(_n(0))._(_n(0)))).toBe(false); }); it('0 lt 1 is True', () => { - expect($b(lt._(_(0))._(_(1)))).toBe(true); + expect($b(lt._(_n(0))._(_n(1)))).toBe(true); }); it('1 lt 0 is False', () => { - expect($b(lt._(_(1))._(_(0)))).toBe(false); + expect($b(lt._(_n(1))._(_n(0)))).toBe(false); }); it('3 lt 3 is False', () => { - expect($b(lt._(_(3))._(_(3)))).toBe(false); + expect($b(lt._(_n(3))._(_n(3)))).toBe(false); }); it('3 lt 7 is True', () => { - expect($b(lt._(_(3))._(_(7)))).toBe(true); + expect($b(lt._(_n(3))._(_n(7)))).toBe(true); }); it('7 lt 3 is False', () => { - expect($b(lt._(_(7))._(_(3)))).toBe(false); + expect($b(lt._(_n(7))._(_n(3)))).toBe(false); }); it('handles infinity', () => { - expect($b(lt._(_(7))._(infinity))).toBe(true); - expect($b(lt._(infinity)._(_(7)))).toBe(false); + expect($b(lt._(_n(7))._(infinity))).toBe(true); + expect($b(lt._(infinity)._(_n(7)))).toBe(false); }); }); describe('le', () => { it('0 le 0 is True', () => { - expect($b(le._(_(0))._(_(0)))).toBe(true); + expect($b(le._(_n(0))._(_n(0)))).toBe(true); }); it('0 le 1 is True', () => { - expect($b(le._(_(0))._(_(1)))).toBe(true); + expect($b(le._(_n(0))._(_n(1)))).toBe(true); }); it('1 le 0 is False', () => { - expect($b(le._(_(1))._(_(0)))).toBe(false); + expect($b(le._(_n(1))._(_n(0)))).toBe(false); }); it('3 le 3 is True', () => { - expect($b(le._(_(3))._(_(3)))).toBe(true); + expect($b(le._(_n(3))._(_n(3)))).toBe(true); }); it('3 le 7 is True', () => { - expect($b(le._(_(3))._(_(7)))).toBe(true); + expect($b(le._(_n(3))._(_n(7)))).toBe(true); }); it('7 le 3 is False', () => { - expect($b(le._(_(7))._(_(3)))).toBe(false); + expect($b(le._(_n(7))._(_n(3)))).toBe(false); }); it('handles infinity', () => { - expect($b(le._(_(7))._(infinity))).toBe(true); - expect($b(le._(infinity)._(_(7)))).toBe(false); + expect($b(le._(_n(7))._(infinity))).toBe(true); + expect($b(le._(infinity)._(_n(7)))).toBe(false); }); }); describe('eq', () => { it('0 eq 0 is True', () => { - expect($b(eq._(_(0))._(_(0)))).toBe(true); + expect($b(eq._(_n(0))._(_n(0)))).toBe(true); }); it('0 eq 1 is False', () => { - expect($b(eq._(_(0))._(_(1)))).toBe(false); + expect($b(eq._(_n(0))._(_n(1)))).toBe(false); }); it('1 eq 0 is False', () => { - expect($b(eq._(_(1))._(_(0)))).toBe(false); + expect($b(eq._(_n(1))._(_n(0)))).toBe(false); }); it('3 eq 3 is True', () => { - expect($b(eq._(_(3))._(_(3)))).toBe(true); + expect($b(eq._(_n(3))._(_n(3)))).toBe(true); }); it('3 eq 7 is False', () => { - expect($b(eq._(_(3))._(_(7)))).toBe(false); + expect($b(eq._(_n(3))._(_n(7)))).toBe(false); }); it('7 eq 3 is False', () => { - expect($b(eq._(_(7))._(_(3)))).toBe(false); + expect($b(eq._(_n(7))._(_n(3)))).toBe(false); }); it('handles infinity', () => { - expect($b(eq._(_(7))._(infinity))).toBe(false); - expect($b(eq._(infinity)._(_(7)))).toBe(false); + expect($b(eq._(_n(7))._(infinity))).toBe(false); + expect($b(eq._(infinity)._(_n(7)))).toBe(false); }); }); describe('ge', () => { it('0 ge 0 is True', () => { - expect($b(ge._(_(0))._(_(0)))).toBe(true); + expect($b(ge._(_n(0))._(_n(0)))).toBe(true); }); it('0 ge 1 is False', () => { - expect($b(ge._(_(0))._(_(1)))).toBe(false); + expect($b(ge._(_n(0))._(_n(1)))).toBe(false); }); it('1 ge 0 is True', () => { - expect($b(ge._(_(1))._(_(0)))).toBe(true); + expect($b(ge._(_n(1))._(_n(0)))).toBe(true); }); it('3 ge 3 is True', () => { - expect($b(ge._(_(3))._(_(3)))).toBe(true); + expect($b(ge._(_n(3))._(_n(3)))).toBe(true); }); it('3 ge 7 is False', () => { - expect($b(ge._(_(3))._(_(7)))).toBe(false); + expect($b(ge._(_n(3))._(_n(7)))).toBe(false); }); it('7 ge 3 is True', () => { - expect($b(ge._(_(7))._(_(3)))).toBe(true); + expect($b(ge._(_n(7))._(_n(3)))).toBe(true); }); it('handles infinity', () => { - expect($b(ge._(_(7))._(infinity))).toBe(false); - expect($b(ge._(infinity)._(_(7)))).toBe(true); + expect($b(ge._(_n(7))._(infinity))).toBe(false); + expect($b(ge._(infinity)._(_n(7)))).toBe(true); }); }); describe('gt', () => { it('0 gt 0 is False', () => { - expect($b(gt._(_(0))._(_(0)))).toBe(false); + expect($b(gt._(_n(0))._(_n(0)))).toBe(false); }); it('0 gt 1 is False', () => { - expect($b(gt._(_(0))._(_(1)))).toBe(false); + expect($b(gt._(_n(0))._(_n(1)))).toBe(false); }); it('1 gt 0 is True', () => { - expect($b(gt._(_(1))._(_(0)))).toBe(true); + expect($b(gt._(_n(1))._(_n(0)))).toBe(true); }); it('3 gt 3 is False', () => { - expect($b(gt._(_(3))._(_(3)))).toBe(false); + expect($b(gt._(_n(3))._(_n(3)))).toBe(false); }); it('3 gt 7 is False', () => { - expect($b(gt._(_(3))._(_(7)))).toBe(false); + expect($b(gt._(_n(3))._(_n(7)))).toBe(false); }); it('7 gt 3 is True', () => { - expect($b(gt._(_(7))._(_(3)))).toBe(true); + expect($b(gt._(_n(7))._(_n(3)))).toBe(true); }); it('handles infinity', () => { - expect($b(gt._(_(7))._(infinity))).toBe(false); - expect($b(gt._(infinity)._(_(7)))).toBe(true); + expect($b(gt._(_n(7))._(infinity))).toBe(false); + expect($b(gt._(infinity)._(_n(7)))).toBe(true); }); }); describe('sum', () => { it('0 sum 0 is 0', () => { - expect($(sum._(_(0))._(_(0)))).toBe(0); + expect($n(sum._(_n(0))._(_n(0)))).toBe(0); }); it('0 sum 1 is 1', () => { - expect($(sum._(_(0))._(_(1)))).toBe(1); + expect($n(sum._(_n(0))._(_n(1)))).toBe(1); }); it('1 sum 0 is 1', () => { - expect($(sum._(_(1))._(_(0)))).toBe(1); + expect($n(sum._(_n(1))._(_n(0)))).toBe(1); }); it('3 sum 4 is 7', () => { - expect($(sum._(_(3))._(_(4)))).toBe(7); + expect($n(sum._(_n(3))._(_n(4)))).toBe(7); }); }); describe('sub', () => { it('0 sub 0 is 0', () => { - expect($(sub._(_(0))._(_(0)))).toBe(0); + expect($n(sub._(_n(0))._(_n(0)))).toBe(0); }); it('0 sub 1 is 0', () => { - expect($(sub._(_(0))._(_(1)))).toBe(0); + expect($n(sub._(_n(0))._(_n(1)))).toBe(0); }); it('1 sub 0 is 1', () => { - expect($(sub._(_(1))._(_(0)))).toBe(1); + expect($n(sub._(_n(1))._(_n(0)))).toBe(1); }); it('7 sub 4 is 3', () => { - expect($(sub._(_(7))._(_(4)))).toBe(3); + expect($n(sub._(_n(7))._(_n(4)))).toBe(3); }); }); describe('mul', () => { it('0 mul 0 is 0', () => { - expect($(mul._(_(0))._(_(0)))).toBe(0); + expect($n(mul._(_n(0))._(_n(0)))).toBe(0); }); it('0 mul 10 is 0', () => { - expect($(mul._(_(0))._(_(10)))).toBe(0); + expect($n(mul._(_n(0))._(_n(10)))).toBe(0); }); it('10 mul 0 is 0', () => { - expect($(mul._(_(1))._(_(0)))).toBe(0); + expect($n(mul._(_n(1))._(_n(0)))).toBe(0); }); it('1 mul 10 is 10', () => { - expect($(mul._(_(1))._(_(10)))).toBe(10); + expect($n(mul._(_n(1))._(_n(10)))).toBe(10); }); it('10 mul 1 is 10', () => { - expect($(mul._(_(10))._(_(1)))).toBe(10); + expect($n(mul._(_n(10))._(_n(1)))).toBe(10); }); it('3 mul 4 is 12', () => { - expect($(mul._(_(3))._(_(4)))).toBe(12); + expect($n(mul._(_n(3))._(_n(4)))).toBe(12); }); it('0 mul ignores second argument', () => { - expect($(mul._(_(0))._(undef))).toBe(0); + expect($n(mul._(_n(0))._(undef))).toBe(0); }); }); describe('div', () => { it('0 div 10 is 0', () => { - expect($(div._(_(0))._(_(10)))).toBe(0); + expect($n(div._(_n(0))._(_n(10)))).toBe(0); }); it('1 div 10 is 0', () => { - expect($(div._(_(1))._(_(10)))).toBe(0); + expect($n(div._(_n(1))._(_n(10)))).toBe(0); }); it('10 div 1 is 10', () => { - expect($(div._(_(10))._(_(1)))).toBe(10); + expect($n(div._(_n(10))._(_n(1)))).toBe(10); }); it('10 div 5 is 2', () => { - expect($(div._(_(10))._(_(5)))).toBe(2); + expect($n(div._(_n(10))._(_n(5)))).toBe(2); }); it('10 div 3 is 3', () => { - expect($(div._(_(10))._(_(3)))).toBe(3); + expect($n(div._(_n(10))._(_n(3)))).toBe(3); }); it.failing('0 div ignores second argument', () => { - expect($(div._(_(0))._(undef))).toBe(0); + expect($n(div._(_n(0))._(undef))).toBe(0); }); }); describe('mod', () => { it('0 mod 10 is 0', () => { - expect($(mod._(_(0))._(_(10)))).toBe(0); + expect($n(mod._(_n(0))._(_n(10)))).toBe(0); }); it('1 mod 10 is 1', () => { - expect($(mod._(_(1))._(_(10)))).toBe(1); + expect($n(mod._(_n(1))._(_n(10)))).toBe(1); }); it('10 mod 1 is 0', () => { - expect($(mod._(_(10))._(_(1)))).toBe(0); + expect($n(mod._(_n(10))._(_n(1)))).toBe(0); }); it('10 mod 5 is 0', () => { - expect($(mod._(_(10))._(_(5)))).toBe(0); + expect($n(mod._(_n(10))._(_n(5)))).toBe(0); }); it('10 mod 3 is 1', () => { - expect($(mod._(_(10))._(_(3)))).toBe(1); + expect($n(mod._(_n(10))._(_n(3)))).toBe(1); }); it.failing('0 mod ignores second argument', () => { - expect($(mod._(_(0))._(undef))).toBe(0); + expect($n(mod._(_n(0))._(undef))).toBe(0); + }); + }); + + describe('show', () => { + it('show 0 is "0"', () => { + expect($s(show._(_n(0)))).toBe('0'); + }); + + it('show 1 is "1"', () => { + expect($s(show._(_n(1)))).toBe('1'); + }); + + it('show 255 is "255"', () => { + expect($s(show._(_n(255)))).toBe('255'); + }); + + it('show 1000 is "1000"', () => { + expect($s(show._(_n(1000)))).toBe('1000'); }); }); }); diff --git a/test/pair.spec.ts b/test/pair.spec.ts index 4a2f4ca..ba5e998 100644 --- a/test/pair.spec.ts +++ b/test/pair.spec.ts @@ -1,9 +1,10 @@ import { describe, expect, it } from '@jest/globals'; import { undef } from '../src/core'; import { toNOrd as $o, NOrd } from '../src/ord'; -import { toBoolean as $b, fromBoolean as _b, cmp as bcmp, eq as beq, not } from '../src/bool'; -import { toNumber as $n, fromNumber as _n, cmp as ncmp, eq as neq, succ } from '../src/num'; -import { Pair, both, cmp, eq, first, fst, ge, gt, le, lt, second, snd } from '../src/pair'; +import { toBoolean as $b, fromBoolean as _b, cmp as bcmp, eq as beq, show as bshow, not } from '../src/bool'; +import { toNumber as $n, fromNumber as _n, cmp as ncmp, eq as neq, show as nshow, succ } from '../src/num'; +import { Pair, both, cmp, eq, first, fst, ge, gt, le, lt, second, show, snd } from '../src/pair'; +import { toString as $s } from '../src/string'; describe('Pair', () => { describe('fst', () => { @@ -208,4 +209,22 @@ describe('Pair', () => { expect($b(gt._(bcmp)._(undef)._(Pair._(_b(false))._(undef))._(Pair._(_b(true))._(undef)))).toBe(false); }); }); + + describe('show', () => { + it('show (False, 0) is "(False, 0)"', () => { + expect($s(show._(bshow)._(nshow)._(Pair._(_b(false))._(_n(0))))).toBe('(False, 0)'); + }); + + it('show (False, 1) is "(False, 1)"', () => { + expect($s(show._(bshow)._(nshow)._(Pair._(_b(false))._(_n(1))))).toBe('(False, 1)'); + }); + + it('show (True, 0) is "(True, 0)"', () => { + expect($s(show._(bshow)._(nshow)._(Pair._(_b(true))._(_n(0))))).toBe('(True, 0)'); + }); + + it('show (True, 1) is "(True, 1)"', () => { + expect($s(show._(bshow)._(nshow)._(Pair._(_b(true))._(_n(1))))).toBe('(True, 1)'); + }); + }); }); diff --git a/test/string.spec.ts b/test/string.spec.ts index b82dabc..887e749 100644 --- a/test/string.spec.ts +++ b/test/string.spec.ts @@ -2,11 +2,12 @@ import { describe, expect, it } from '@jest/globals'; import { L, _, undef } from '../src/core'; import { NOrd, toNOrd } from '../src/ord'; import { toBoolean as $b } from '../src/bool'; +import { toNumber as $n, Zero, gt as ngt } from '../src/num'; import { toChar as $c, fromChar as _c } from '../src/char'; -import { toString as $s, Cons, Empty, String, fromString as _s, cmp, concat, eq, ge, gt, le, lt } from '../src/string'; +import { toString as $s, Cons, Empty, String, fromString as _s, append, cmp, empty, eq, ge, gt, le, len, lt, show } from '../src/string'; describe('String', () => { - const infinite: String = new L(() => Cons._(_c('a'))._(infinite).value); ; + const infinite: String = Cons._(_c('a'))._(new L(() => infinite.value)); describe('toString', () => { it('converts ""', () => { @@ -36,21 +37,57 @@ describe('String', () => { }); }); - describe('concat', () => { - it('"" concat "" is ""', () => { - expect($s(concat._(Empty)._(Empty))).toBe(''); + describe('empty', () => { + it('empty "" is True', () => { + expect($b(empty._(_s('')))).toEqual(true); }); - it('"a" concat "b" is "ab"', () => { - expect($s(concat._(_s('a'))._(_s('b')))).toBe('ab'); + it('empty "a" is False', () => { + expect($b(empty._(_s('a')))).toEqual(false); }); - it('"abc" concat "def" is "abcdef"', () => { - expect($s(concat._(_s('abc'))._(_s('def')))).toBe('abcdef'); + it('empty "ab" is False', () => { + expect($b(empty._(_s('ab')))).toEqual(false); + }); + + it('handles infinite lists', () => { + expect($b(empty._(infinite))).toEqual(false); + }); + }); + + describe('len', () => { + it('len "" is 0', () => { + expect($n(len._(_s('')))).toEqual(0); + }); + + it('len "a" is 1', () => { + expect($n(len._(_s('a')))).toEqual(1); + }); + + it('len "ab" is 2', () => { + expect($n(len._(_s('ab')))).toEqual(2); + }); + + it('handles infinite lists', () => { + expect($b(ngt._(len._(infinite))._(Zero))).toEqual(true); + }); + }); + + describe('append', () => { + it('"" append "" is ""', () => { + expect($s(append._(Empty)._(Empty))).toBe(''); + }); + + it('"a" append "b" is "ab"', () => { + expect($s(append._(_s('a'))._(_s('b')))).toBe('ab'); + }); + + it('"abc" append "def" is "abcdef"', () => { + expect($s(append._(_s('abc'))._(_s('def')))).toBe('abcdef'); }); it('handles infinite strings', () => { - expect($c(concat._(infinite)._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe('a'); + expect($c(append._(infinite)._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe('a'); }); }); @@ -287,4 +324,18 @@ describe('String', () => { expect($b(gt._(infinite)._(_s('abc')))).toEqual(false); }); }); + + describe('show', () => { + it('show "" is """"', () => { + expect($s(show._(_s('')))).toBe('""'); + }); + + it('show "a" is ""a""', () => { + expect($s(show._(_s('a')))).toBe('"a"'); + }); + + it('show "abc" is ""abc""', () => { + expect($s(show._(_s('abc')))).toBe('"abc"'); + }); + }); });