import { describe, expect, it } from '@jest/globals'; import { fromNative as $$, L, _, toNative 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, gt, head, le, lt, map, tail } from '../src/list'; describe('List', () => { const iterate: (n: Num) => List = n => new L(() => Cons._(n)._(iterate(Succ._(n))).value); const infinite: List = iterate(Zero); const _na: (xs: number[]) => List = xs => xs.length === 0 ? Nil : Cons._(_nn(xs[0]))._(new L(() => _na(xs.slice(1)).value)); const $na: (xs: List) => number[] = xs => __(xs._($$([]))._(_(x => _(xs => $$([$nn(x), ...$na(xs)]))))); describe('toArray', () => { it('converts []', () => { expect($a(Nil)).toEqual([]); }); it('converts [0]', () => { expect($a(Cons._(_n(0))._(Nil)).map($n)).toEqual([0]); }); it('converts [0, 1]', () => { expect($a(Cons._(_n(0))._(Cons._(_n(1))._(Nil))).map($n)).toEqual([0, 1]); }); }); describe('fromArray', () => { it('converts []', () => { expect($a(_a([]))).toEqual([]); }); it('converts [0]', () => { expect($a(_a([0].map(_n))).map($n)).toEqual([0]); }); it('converts 2', () => { expect($a(_a([0, 1].map(_n))).map($n)).toEqual([0, 1]); }); }); describe('cons', () => { it('0 cons Nil is [0]', () => { expect($na(cons._(_n(0))._(Nil))).toEqual([0]); }); it('0 cons [1] is [0, 1]', () => { expect($na(cons._(_n(0))._(_na([1])))).toEqual([0, 1]); }); it('0 cons [1, 2] is [0, 1, 2]', () => { expect($na(cons._(_n(0))._(_na([1, 2])))).toEqual([0, 1, 2]); }); it('handles infinite lists', () => { expect($n(cons._(_n(0))._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe(0); }); }); describe('concat', () => { it('Nil concat Nil is Nil', () => { expect($na(concat._(Nil)._(Nil))).toEqual([]); }); it('[0] concat [1] is [0, 1]', () => { expect($na(concat._(_na([0]))._(_na([1])))).toEqual([0, 1]); }); 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('handles infinite lists', () => { expect($n(concat._(infinite)._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe(0); }); }); describe('head', () => { it('returns nothing from Nil', () => { expect(() => __(head._(Nil))).toThrow(); }); it('returns only item', () => { expect($n(head._(_na([0])))).toBe(0); }); it('returns first item', () => { expect($n(head._(_na([0, 1])))).toBe(0); }); it('handles infinite lists', () => { expect($n(head._(infinite))).toBe(0); }); }); describe('tail', () => { it('drops nothing from Nil', () => { expect(() => $na(tail._(Nil))).toThrow(); }); it('drops only item', () => { expect($na(tail._(_na([0])))).toEqual([]); }); it('drops first item', () => { expect($na(tail._(_na([0, 1])))).toEqual([1]); }); it('handles infinite lists', () => { expect($n(head._(tail._(infinite)))).toBe(1); }); }); describe('foldl', () => { it('folds Nil', () => { expect($n(foldl._(sum)._(Zero)._(_na([])))).toBe(0); }); it('folds single item', () => { expect($n(foldl._(sum)._(Zero)._(_na([1])))).toBe(1); }); it('folds several items', () => { expect($n(foldl._(sum)._(Zero)._(_na([1, 2])))).toBe(3); }); }); describe('foldlz', () => { it('does not fold Nil', () => { expect(() => $n(foldlz._(sum)._(Nil))).toThrow(); }); it('folds single item', () => { expect($n(foldlz._(sum)._(_na([1])))).toBe(1); }); it('folds several items', () => { expect($n(foldlz._(sum)._(_na([1, 2])))).toBe(3); }); }); describe('foldr', () => { it('folds Nil', () => { expect($n(foldr._(sum)._(Zero)._(_na([])))).toBe(0); }); it('folds single item', () => { expect($n(foldr._(sum)._(Zero)._(_na([1])))).toBe(1); }); it('folds several items', () => { expect($n(foldr._(sum)._(Zero)._(_na([1, 2])))).toBe(3); }); it('handles infinite lists', () => { expect($n( foldr ._(_(x => _(a => sum._(x)._(iif._(eqn._(_n(5))._(x))._(Zero)._(a))))) ._(Zero) ._(infinite))) .toBe(15); }); }); describe('foldrz', () => { it('does not fold Nil', () => { expect(() => $n(foldrz._(sum)._(Nil))).toThrow(); }); it.failing('folds single item', () => { expect($n(foldrz._(sum)._(_na([1])))).toBe(1); }); it.failing('folds several items', () => { expect($n(foldrz._(sum)._(_na([1, 2])))).toBe(3); }); it.failing('handles infinite lists', () => { expect($n( foldrz ._(_(x => _(a => sum._(x)._(iif._(eqn._(_n(5))._(x))._(Zero)._(a))))) ._(infinite))) .toBe(15); }); }); describe('cmp', () => { it('Nil cmp Nil is EQ', () => { expect($o(cmp._(cmpn)._(_na([]))._(_na([])))).toEqual(NOrd.EQ); }); it('Nil cmp [0, 1, 2] is LT', () => { expect($o(cmp._(cmpn)._(_na([]))._(_na([0, 1, 2])))).toEqual(NOrd.LT); }); it('[0, 1, 2] cmp Nil is GT', () => { expect($o(cmp._(cmpn)._(_na([0, 1, 2]))._(_na([])))).toEqual(NOrd.GT); }); it('[0] cmp [0, 1, 2] is LT', () => { expect($o(cmp._(cmpn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(NOrd.LT); }); it('[0, 1, 2] cmp [0] is GT', () => { expect($o(cmp._(cmpn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(NOrd.GT); }); it('[1, 2, 0] cmp [0, 1, 2] is GT', () => { expect($o(cmp._(cmpn)._(_na([1, 2, 0]))._(_na([0, 1, 2])))).toEqual(NOrd.GT); }); it('[0, 1, 2] cmp [1, 2, 0] is LT', () => { expect($o(cmp._(cmpn)._(_na([0, 1, 2]))._(_na([1, 2, 0])))).toEqual(NOrd.LT); }); it('[0, 1, 2] cmp [0, 1, 2] is EQ', () => { expect($o(cmp._(cmpn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(NOrd.EQ); }); it('handles infinite lists', () => { expect($o(cmp._(cmpn)._(_na([0, 1, 2]))._(infinite))).toEqual(NOrd.LT); expect($o(cmp._(cmpn)._(infinite)._(_na([0, 1, 2])))).toEqual(NOrd.GT); }); }); describe('lt', () => { it('Nil lt Nil is False', () => { expect($b(lt._(cmpn)._(_na([]))._(_na([])))).toEqual(false); }); it('Nil lt [0, 1, 2] is True', () => { expect($b(lt._(cmpn)._(_na([]))._(_na([0, 1, 2])))).toEqual(true); }); it('[0, 1, 2] lt Nil is False', () => { expect($b(lt._(cmpn)._(_na([0, 1, 2]))._(_na([])))).toEqual(false); }); it('[0] lt [0, 1, 2] is True', () => { expect($b(lt._(cmpn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(true); }); it('[0, 1, 2] lt [0] is False', () => { expect($b(lt._(cmpn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(false); }); it('[1, 2, 0] lt [0, 1, 2] is False', () => { expect($b(lt._(cmpn)._(_na([1, 2, 0]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] lt [1, 2, 0] is True', () => { expect($b(lt._(cmpn)._(_na([0, 1, 2]))._(_na([1, 2, 0])))).toEqual(true); }); it('[0, 1, 2] lt [0, 1, 2] is False', () => { expect($b(lt._(cmpn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(false); }); it('handles infinite lists', () => { expect($b(lt._(cmpn)._(_na([0, 1, 2]))._(infinite))).toEqual(true); expect($b(lt._(cmpn)._(infinite)._(_na([0, 1, 2])))).toEqual(false); }); }); describe('le', () => { it('Nil le Nil is True', () => { expect($b(le._(cmpn)._(_na([]))._(_na([])))).toEqual(true); }); it('Nil le [0, 1, 2] is True', () => { expect($b(le._(cmpn)._(_na([]))._(_na([0, 1, 2])))).toEqual(true); }); it('[0, 1, 2] le Nil is False', () => { expect($b(le._(cmpn)._(_na([0, 1, 2]))._(_na([])))).toEqual(false); }); it('[0] le [0, 1, 2] is True', () => { expect($b(le._(cmpn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(true); }); it('[0, 1, 2] le [0] is False', () => { expect($b(le._(cmpn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(false); }); it('[1, 2, 0] le [0, 1, 2] is False', () => { expect($b(le._(cmpn)._(_na([1, 2, 0]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] le [1, 2, 0] is True', () => { expect($b(le._(cmpn)._(_na([0, 1, 2]))._(_na([1, 2, 0])))).toEqual(true); }); it('[0, 1, 2] le [0, 1, 2] is True', () => { expect($b(le._(cmpn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(true); }); it('handles infinite lists', () => { expect($b(le._(cmpn)._(_na([0, 1, 2]))._(infinite))).toEqual(true); expect($b(le._(cmpn)._(infinite)._(_na([0, 1, 2])))).toEqual(false); }); }); describe('eq', () => { it('Nil eq Nil is True', () => { expect($b(eq._(eqn)._(_na([]))._(_na([])))).toEqual(true); }); it('Nil eq [0, 1, 2] is False', () => { expect($b(eq._(eqn)._(_na([]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] eq Nil is False', () => { expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([])))).toEqual(false); }); it('[0] eq [0, 1, 2] is False', () => { expect($b(eq._(eqn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] eq [0] is False', () => { expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(false); }); it('[1, 2, 0] eq [0, 1, 2] is False', () => { expect($b(eq._(eqn)._(_na([1, 2, 0]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] eq [1, 2, 0] is False', () => { expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([1, 2, 0])))).toEqual(false); }); it('[0, 1, 2] eq [0, 1, 2] is True', () => { expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(true); }); it('handles infinite lists', () => { expect($b(eq._(eqn)._(_na([0, 1, 2]))._(infinite))).toEqual(false); expect($b(eq._(eqn)._(infinite)._(_na([0, 1, 2])))).toEqual(false); }); }); describe('ge', () => { it('Nil ge Nil is True', () => { expect($b(ge._(cmpn)._(_na([]))._(_na([])))).toEqual(true); }); it('Nil ge [0, 1, 2] is False', () => { expect($b(ge._(cmpn)._(_na([]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] ge Nil is True', () => { expect($b(ge._(cmpn)._(_na([0, 1, 2]))._(_na([])))).toEqual(true); }); it('[0] ge [0, 1, 2] is False', () => { expect($b(ge._(cmpn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] ge [0] is True', () => { expect($b(ge._(cmpn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(true); }); it('[1, 2, 0] ge [0, 1, 2] is True', () => { expect($b(ge._(cmpn)._(_na([1, 2, 0]))._(_na([0, 1, 2])))).toEqual(true); }); it('[0, 1, 2] ge [1, 2, 0] is False', () => { expect($b(ge._(cmpn)._(_na([0, 1, 2]))._(_na([1, 2, 0])))).toEqual(false); }); it('[0, 1, 2] ge [0, 1, 2] is True', () => { expect($b(ge._(cmpn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(true); }); it('handles infinite lists', () => { expect($b(ge._(cmpn)._(_na([0, 1, 2]))._(infinite))).toEqual(false); expect($b(ge._(cmpn)._(infinite)._(_na([0, 1, 2])))).toEqual(true); }); }); describe('gt', () => { it('Nil gt Nil is False', () => { expect($b(gt._(cmpn)._(_na([]))._(_na([])))).toEqual(false); }); it('Nil gt [0, 1, 2] is False', () => { expect($b(gt._(cmpn)._(_na([]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] gt Nil is True', () => { expect($b(gt._(cmpn)._(_na([0, 1, 2]))._(_na([])))).toEqual(true); }); it('[0] gt [0, 1, 2] is False', () => { expect($b(gt._(cmpn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(false); }); it('[0, 1, 2] gt [0] is True', () => { expect($b(gt._(cmpn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(true); }); it('[1, 2, 0] gt [0, 1, 2] is True', () => { expect($b(gt._(cmpn)._(_na([1, 2, 0]))._(_na([0, 1, 2])))).toEqual(true); }); it('[0, 1, 2] gt [1, 2, 0] is False', () => { expect($b(gt._(cmpn)._(_na([0, 1, 2]))._(_na([1, 2, 0])))).toEqual(false); }); it('[0, 1, 2] gt [0, 1, 2] is False', () => { expect($b(gt._(cmpn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(false); }); it('handles infinite lists', () => { expect($b(gt._(cmpn)._(_na([0, 1, 2]))._(infinite))).toEqual(false); expect($b(gt._(cmpn)._(infinite)._(_na([0, 1, 2])))).toEqual(true); }); }); describe('map', () => { it('maps Nil', () => { expect($na(map._(succ)._(_na([])))).toEqual([]); }); it('maps only item', () => { expect($na(map._(succ)._(_na([0])))).toEqual([1]); }); it('maps several items', () => { expect($na(map._(succ)._(_na([0, 1])))).toEqual([1, 2]); }); it('handles infinite lists', () => { expect($n(head._(map._(succ)._(infinite)))).toBe(1); }); }); describe('filter', () => { it('filter Nil', () => { expect($na(filter._(odd)._(_na([])))).toEqual([]); }); it('filters only item', () => { expect($na(filter._(odd)._(_na([])))).toEqual([]); }); it('filters several items', () => { expect($na(filter._(odd)._(_na([0, 1])))).toEqual([1]); }); it('handles infinite lists', () => { expect($n(head._(filter._(odd)._(infinite)))).toBe(1); }); }); describe('any', () => { it('any Nil is False', () => { expect($b(any._(odd)._(_na([])))).toEqual(false); }); it('any for no matching item is False', () => { expect($b(any._(odd)._(_na([0, 2])))).toEqual(false); }); it('any for matching item is True', () => { expect($b(any._(odd)._(_na([0, 1, 2])))).toEqual(true); }); it('handles infinite lists', () => { expect($b(any._(odd)._(infinite))).toEqual(true); }); }); describe('all', () => { it('all Nil is True', () => { expect($b(all._(even)._(_na([])))).toEqual(true); }); it('all for non-matching item is False', () => { expect($b(all._(even)._(_na([0, 1, 2])))).toEqual(false); }); it('all for no non-matching item is True', () => { expect($b(all._(even)._(_na([0, 2])))).toEqual(true); }); it('handles infinite lists', () => { expect($b(all._(even)._(infinite))).toEqual(false); }); }); });