import { describe, expect, it } from '@jest/globals'; import { L, toNative } from '../src/core'; import { toNumber as $n, Num, Succ, Zero, fromNumber as _n, odd, succ, sum } from '../src/num'; import { toArray as $, toNumberArray as $na, Cons, List, Nil, fromArray as _, fromNumberArray as _na, filter, foldl, foldlz, foldr, foldrz, head, map, tail } from '../src/list'; describe('List', () => { const iterate: (n: Num) => List = n => new L(() => Cons._(n)._(iterate(Succ._(n))).value); describe('toArray', () => { it('converts []', () => { expect($(Nil)).toEqual([]); }); it('converts [0]', () => { expect($(Cons._(_n(0))._(Nil)).map($n)).toEqual([0]); }); it('converts [0, 1]', () => { expect($(Cons._(_n(0))._(Cons._(_n(1))._(Nil))).map($n)).toEqual([0, 1]); }); }); describe('fromArray', () => { it('converts []', () => { expect($(_([]))).toEqual([]); }); it('converts [0]', () => { expect($(_([0].map(_n))).map($n)).toEqual([0]); }); it('converts 2', () => { expect($(_([0, 1].map(_n))).map($n)).toEqual([0, 1]); }); }); describe('head', () => { it('returns nothing from empty list', () => { expect(() => head._(Nil)).not.toThrow(); expect(() => toNative(head._(Nil))).toThrow(); }); it('returns only item', () => { expect(head).toDeferEvaluationOf(_na([0])); expect($n(head._(_na([0])))).toBe(0); }); it('returns first item', () => { expect(head).toDeferEvaluationOf(_na([0, 1])); expect($n(head._(_na([0, 1])))).toBe(0); }); it('handles infinite lists', () => { expect($n(head._(iterate(Zero)))).toBe(0); }); }); describe('tail', () => { it('drops nothing from empty list', () => { expect(() => tail._(Nil)).not.toThrow(); expect(() => $na(tail._(Nil))).toThrow(); }); it('drops only item', () => { expect(tail).toDeferEvaluationOf(_na([0])); expect($na(tail._(_na([0])))).toEqual([]); }); it('drops first item', () => { expect(tail).toDeferEvaluationOf(_na([0, 1])); expect($na(tail._(_na([0, 1])))).toEqual([1]); }); it('handles infinite lists', () => { expect($n(head._(tail._(iterate(Zero))))).toBe(1); }); }); describe('foldl', () => { it('folds empty list', () => { expect(foldl._(sum)).toDeferEvaluationOf(Zero, _na([])); expect($n(foldl._(sum)._(Zero)._(_na([])))).toBe(0); }); it('folds single item', () => { expect(foldl._(sum)).toDeferEvaluationOf(Zero, _na([1])); expect($n(foldl._(sum)._(Zero)._(_na([1])))).toBe(1); }); it('folds several items', () => { expect(foldl._(sum)).toDeferEvaluationOf(Zero, _na([1, 2])); expect($n(foldl._(sum)._(Zero)._(_na([1, 2])))).toBe(3); }); }); describe('foldlz', () => { it('does not fold empty list', () => { expect(() => foldlz._(sum)._(Nil)).not.toThrow(); expect(() => $n(foldlz._(sum)._(Nil))).toThrow(); }); it('folds single item', () => { expect(foldlz._(sum)).toDeferEvaluationOf(_na([1])); expect($n(foldlz._(sum)._(_na([1])))).toBe(1); }); it('folds several items', () => { expect(foldlz._(sum)).toDeferEvaluationOf(_na([1, 2])); expect($n(foldlz._(sum)._(_na([1, 2])))).toBe(3); }); }); describe('foldr', () => { it('folds empty list', () => { expect(foldr._(sum)).toDeferEvaluationOf(Zero, _na([])); expect($n(foldr._(sum)._(Zero)._(_na([])))).toBe(0); }); it('folds single item', () => { expect(foldr._(sum)).toDeferEvaluationOf(Zero, _na([1])); expect($n(foldr._(sum)._(Zero)._(_na([1])))).toBe(1); }); it('folds several items', () => { expect(foldr._(sum)).toDeferEvaluationOf(Zero, _na([1, 2])); expect($n(foldr._(sum)._(Zero)._(_na([1, 2])))).toBe(3); }); // it('handles infinite lists', () => { // expect(foldr, Lazy>(x => _(a => // iif> // (x.call(x => fromBoolean(x === 0))) // .call( // (x).call( // (x.call(x => a.call(a => _(x + a))))))) // ).call((fromNumber(0)).call((iterate(-5))))).toEvaluateTo(-15); // }); }); describe('foldrz', () => { it('does not fold empty list', () => { expect(() => foldrz._(sum)._(Nil)).not.toThrow(); expect(() => $n(foldrz._(sum)._(Nil))).toThrow(); }); it.failing('folds single item', () => { expect(foldrz._(sum)).toDeferEvaluationOf(_na([1])); expect($n(foldrz._(sum)._(_na([1])))).toBe(1); }); it.failing('folds several items', () => { expect(foldrz._(sum)).toDeferEvaluationOf(_na([1, 2])); expect($n(foldrz._(sum)._(_na([1, 2])))).toBe(3); }); // it.failing('handles infinite lists', () => { // expect(foldrz>(x => _(a => // iif> // (x.call(x => fromBoolean(x === 0))) // .call( // (x).call( // (x.call(x => a.call(a => _(x + a))))))) // ).call((iterate(-5)))).toEvaluateTo(-10); // }); }); describe('map', () => { it('maps empty list', () => { expect(map._(succ)).toDeferEvaluationOf(_na([])); expect($na(map._(succ)._(_na([])))).toEqual([]); }); it('maps only item', () => { expect(map._(succ)).toDeferEvaluationOf(_na([0])); expect($na(map._(succ)._(_na([0])))).toEqual([1]); }); it('maps several items', () => { expect(map._(succ)).toDeferEvaluationOf(_na([0, 1])); expect($na(map._(succ)._(_na([0, 1])))).toEqual([1, 2]); }); it('handles infinite lists', () => { expect($n(head._(map._(succ)._(iterate(Zero))))).toBe(1); }); }); describe('filter', () => { it('filter empty list', () => { expect(filter._(odd)).toDeferEvaluationOf(_na([])); expect($na(filter._(odd)._(_na([])))).toEqual([]); }); it('filters only item', () => { expect(filter._(odd)).toDeferEvaluationOf(_na([0])); expect($na(filter._(odd)._(_na([])))).toEqual([]); }); it('filters several items', () => { expect(filter._(odd)).toDeferEvaluationOf(_na([0, 1])); expect($na(filter._(odd)._(_na([0, 1])))).toEqual([1]); }); it('handles infinite lists', () => { expect($n(head._(filter._(odd)._(iterate(Zero))))).toBe(1); }); }); });