|
|
|
@ -1,41 +1,44 @@ |
|
|
|
import { describe, expect, it } from '@jest/globals'; |
|
|
|
import { describe, expect, it } from '@jest/globals'; |
|
|
|
import { L, toNative } from '../src/core'; |
|
|
|
import { L, _, toNative } from '../src/core'; |
|
|
|
import { toNumber as $n, Num, Succ, Zero, fromNumber as _n, odd, succ, sum } from '../src/num'; |
|
|
|
import { toBoolean as $b, iif } from '../src/bool'; |
|
|
|
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'; |
|
|
|
import { toNumber as $n, Num, Succ, Zero, fromNumber as _n, eq as eqn, even, odd, succ, sum } from '../src/num'; |
|
|
|
|
|
|
|
import { toArray as $a, toNumberArray as $na, Cons, List, Nil, fromArray as _a, fromNumberArray as _na, all, any, eq, filter, foldl, foldlz, foldr, foldrz, head, map, tail } from '../src/list'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
describe('List', () => { |
|
|
|
describe('List', () => { |
|
|
|
const iterate: (n: Num) => List<Num> = n => new L(() => Cons._(n)._(iterate(Succ._(n))).value); |
|
|
|
const iterate: (n: Num) => List<Num> = n => new L(() => Cons._(n)._(iterate(Succ._(n))).value); |
|
|
|
|
|
|
|
const infinite: List<Num> = iterate(Zero); |
|
|
|
|
|
|
|
|
|
|
|
describe('toArray', () => { |
|
|
|
describe('toArray', () => { |
|
|
|
it('converts []', () => { |
|
|
|
it('converts []', () => { |
|
|
|
expect($(Nil)).toEqual([]); |
|
|
|
expect($a(Nil)).toEqual([]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('converts [0]', () => { |
|
|
|
it('converts [0]', () => { |
|
|
|
expect($(Cons._(_n(0))._(Nil)).map($n)).toEqual([0]); |
|
|
|
expect($a(Cons._(_n(0))._(Nil)).map($n)).toEqual([0]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('converts [0, 1]', () => { |
|
|
|
it('converts [0, 1]', () => { |
|
|
|
expect($(Cons._(_n(0))._(Cons._(_n(1))._(Nil))).map($n)).toEqual([0, 1]); |
|
|
|
expect($a(Cons._(_n(0))._(Cons._(_n(1))._(Nil))).map($n)).toEqual([0, 1]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('fromArray', () => { |
|
|
|
describe('fromArray', () => { |
|
|
|
it('converts []', () => { |
|
|
|
it('converts []', () => { |
|
|
|
expect($(_([]))).toEqual([]); |
|
|
|
expect($a(_a([]))).toEqual([]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('converts [0]', () => { |
|
|
|
it('converts [0]', () => { |
|
|
|
expect($(_([0].map(_n))).map($n)).toEqual([0]); |
|
|
|
expect($a(_a([0].map(_n))).map($n)).toEqual([0]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('converts 2', () => { |
|
|
|
it('converts 2', () => { |
|
|
|
expect($(_([0, 1].map(_n))).map($n)).toEqual([0, 1]); |
|
|
|
expect($a(_a([0, 1].map(_n))).map($n)).toEqual([0, 1]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('head', () => { |
|
|
|
describe('head', () => { |
|
|
|
it('returns nothing from empty list', () => { |
|
|
|
it('returns nothing from Nil', () => { |
|
|
|
expect(() => head._(Nil)).not.toThrow(); |
|
|
|
expect(() => head._(Nil)).not.toThrow(); |
|
|
|
expect(() => toNative(head._(Nil))).toThrow(); |
|
|
|
expect(() => toNative(head._(Nil))).toThrow(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -51,12 +54,12 @@ describe('List', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
it('handles infinite lists', () => { |
|
|
|
expect($n(head._(iterate(Zero)))).toBe(0); |
|
|
|
expect($n(head._(infinite))).toBe(0); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('tail', () => { |
|
|
|
describe('tail', () => { |
|
|
|
it('drops nothing from empty list', () => { |
|
|
|
it('drops nothing from Nil', () => { |
|
|
|
expect(() => tail._(Nil)).not.toThrow(); |
|
|
|
expect(() => tail._(Nil)).not.toThrow(); |
|
|
|
expect(() => $na(tail._(Nil))).toThrow(); |
|
|
|
expect(() => $na(tail._(Nil))).toThrow(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -72,12 +75,12 @@ describe('List', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
it('handles infinite lists', () => { |
|
|
|
expect($n(head._(tail._(iterate(Zero))))).toBe(1); |
|
|
|
expect($n(head._(tail._(infinite)))).toBe(1); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('foldl', () => { |
|
|
|
describe('foldl', () => { |
|
|
|
it('folds empty list', () => { |
|
|
|
it('folds Nil', () => { |
|
|
|
expect(foldl._(sum)).toDeferEvaluationOf(Zero, _na([])); |
|
|
|
expect(foldl._(sum)).toDeferEvaluationOf(Zero, _na([])); |
|
|
|
expect($n(foldl._(sum)._(Zero)._(_na([])))).toBe(0); |
|
|
|
expect($n(foldl._(sum)._(Zero)._(_na([])))).toBe(0); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -94,7 +97,7 @@ describe('List', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('foldlz', () => { |
|
|
|
describe('foldlz', () => { |
|
|
|
it('does not fold empty list', () => { |
|
|
|
it('does not fold Nil', () => { |
|
|
|
expect(() => foldlz._(sum)._(Nil)).not.toThrow(); |
|
|
|
expect(() => foldlz._(sum)._(Nil)).not.toThrow(); |
|
|
|
expect(() => $n(foldlz._(sum)._(Nil))).toThrow(); |
|
|
|
expect(() => $n(foldlz._(sum)._(Nil))).toThrow(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -111,7 +114,7 @@ describe('List', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('foldr', () => { |
|
|
|
describe('foldr', () => { |
|
|
|
it('folds empty list', () => { |
|
|
|
it('folds Nil', () => { |
|
|
|
expect(foldr._(sum)).toDeferEvaluationOf(Zero, _na([])); |
|
|
|
expect(foldr._(sum)).toDeferEvaluationOf(Zero, _na([])); |
|
|
|
expect($n(foldr._(sum)._(Zero)._(_na([])))).toBe(0); |
|
|
|
expect($n(foldr._(sum)._(Zero)._(_na([])))).toBe(0); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -126,19 +129,18 @@ describe('List', () => { |
|
|
|
expect($n(foldr._(sum)._(Zero)._(_na([1, 2])))).toBe(3); |
|
|
|
expect($n(foldr._(sum)._(Zero)._(_na([1, 2])))).toBe(3); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// it('handles infinite lists', () => {
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
// expect(foldr<Lazy<number>, Lazy<number>>(x => _(a =>
|
|
|
|
expect($n( |
|
|
|
// iif<Lazy<number>>
|
|
|
|
foldr |
|
|
|
// (x.call(x => fromBoolean(x === 0)))
|
|
|
|
._(_(x => _(a => iif._(eqn._(x)._(_n(5)))._(x)._(sum._(x)._(a))))) |
|
|
|
// .call(
|
|
|
|
._(Zero) |
|
|
|
// (x).call(
|
|
|
|
._(infinite))) |
|
|
|
// (x.call(x => a.call(a => _(x + a)))))))
|
|
|
|
.toBe(15); |
|
|
|
// ).call((fromNumber(0)).call((iterate(-5))))).toEvaluateTo(-15);
|
|
|
|
}); |
|
|
|
// });
|
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('foldrz', () => { |
|
|
|
describe('foldrz', () => { |
|
|
|
it('does not fold empty list', () => { |
|
|
|
it('does not fold Nil', () => { |
|
|
|
expect(() => foldrz._(sum)._(Nil)).not.toThrow(); |
|
|
|
expect(() => foldrz._(sum)._(Nil)).not.toThrow(); |
|
|
|
expect(() => $n(foldrz._(sum)._(Nil))).toThrow(); |
|
|
|
expect(() => $n(foldrz._(sum)._(Nil))).toThrow(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -153,19 +155,65 @@ describe('List', () => { |
|
|
|
expect($n(foldrz._(sum)._(_na([1, 2])))).toBe(3); |
|
|
|
expect($n(foldrz._(sum)._(_na([1, 2])))).toBe(3); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// it.failing('handles infinite lists', () => {
|
|
|
|
it.failing('handles infinite lists', () => { |
|
|
|
// expect(foldrz<Lazy<number>>(x => _(a =>
|
|
|
|
expect($n( |
|
|
|
// iif<Lazy<number>>
|
|
|
|
foldrz |
|
|
|
// (x.call(x => fromBoolean(x === 0)))
|
|
|
|
._(_(x => _(a => iif._(eqn._(x)._(_n(5)))._(x)._(sum._(x)._(a))))) |
|
|
|
// .call(
|
|
|
|
._(infinite))) |
|
|
|
// (x).call(
|
|
|
|
.toBe(15); |
|
|
|
// (x.call(x => a.call(a => _(x + a)))))))
|
|
|
|
}); |
|
|
|
// ).call((iterate(-5)))).toEvaluateTo(-10);
|
|
|
|
}); |
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
describe('eq', () => { |
|
|
|
|
|
|
|
it('Nil eq Nil is True', () => { |
|
|
|
|
|
|
|
expect(eq).toDeferEvaluationOf(eqn, _na([]), _na([])); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([]))._(_na([])))).toEqual(true); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('Nil eq [0, 1, 2] is False', () => { |
|
|
|
|
|
|
|
expect(eq).toDeferEvaluationOf(eqn, _na([]), _na([0, 1, 2])); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([]))._(_na([0, 1, 2])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('[0, 1, 2] eq Nil is False', () => { |
|
|
|
|
|
|
|
expect(eq).toDeferEvaluationOf(eqn, _na([0, 1, 2]), _na([])); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('[0] eq [0, 1, 2] is False', () => { |
|
|
|
|
|
|
|
expect(eq).toDeferEvaluationOf(eqn, _na([0]), _na([0, 1, 2])); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([0]))._(_na([0, 1, 2])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('[0, 1, 2] eq [0] is False', () => { |
|
|
|
|
|
|
|
expect(eq).toDeferEvaluationOf(eqn, _na([0, 1, 2]), _na([0])); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([0])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('[1, 2, 0] eq [0, 1, 2] is False', () => { |
|
|
|
|
|
|
|
expect(eq).toDeferEvaluationOf(eqn, _na([1, 2, 0]), _na([0, 1, 2])); |
|
|
|
|
|
|
|
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(eq).toDeferEvaluationOf(eqn, _na([0, 1, 2]), _na([1, 2, 0])); |
|
|
|
|
|
|
|
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(eq).toDeferEvaluationOf(eqn, _na([0, 1, 2]), _na([0, 1, 2])); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([0, 1, 2]))._(_na([0, 1, 2])))).toEqual(true); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(infinite)._(_na([0, 1, 2])))).toEqual(false); |
|
|
|
|
|
|
|
expect($b(eq._(eqn)._(_na([0, 1, 2]))._(infinite))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('map', () => { |
|
|
|
describe('map', () => { |
|
|
|
it('maps empty list', () => { |
|
|
|
it('maps Nil', () => { |
|
|
|
expect(map._(succ)).toDeferEvaluationOf(_na([])); |
|
|
|
expect(map._(succ)).toDeferEvaluationOf(_na([])); |
|
|
|
expect($na(map._(succ)._(_na([])))).toEqual([]); |
|
|
|
expect($na(map._(succ)._(_na([])))).toEqual([]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -181,12 +229,12 @@ describe('List', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
it('handles infinite lists', () => { |
|
|
|
expect($n(head._(map._(succ)._(iterate(Zero))))).toBe(1); |
|
|
|
expect($n(head._(map._(succ)._(infinite)))).toBe(1); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe('filter', () => { |
|
|
|
describe('filter', () => { |
|
|
|
it('filter empty list', () => { |
|
|
|
it('filter Nil', () => { |
|
|
|
expect(filter._(odd)).toDeferEvaluationOf(_na([])); |
|
|
|
expect(filter._(odd)).toDeferEvaluationOf(_na([])); |
|
|
|
expect($na(filter._(odd)._(_na([])))).toEqual([]); |
|
|
|
expect($na(filter._(odd)._(_na([])))).toEqual([]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
@ -202,7 +250,49 @@ describe('List', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
it('handles infinite lists', () => { |
|
|
|
expect($n(head._(filter._(odd)._(iterate(Zero))))).toBe(1); |
|
|
|
expect($n(head._(filter._(odd)._(infinite)))).toBe(1); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
describe('any', () => { |
|
|
|
|
|
|
|
it('any Nil is False', () => { |
|
|
|
|
|
|
|
expect(any._(odd)).toDeferEvaluationOf(_na([])); |
|
|
|
|
|
|
|
expect($b(any._(odd)._(_na([])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('any for no matching item is False', () => { |
|
|
|
|
|
|
|
expect(any._(odd)).toDeferEvaluationOf(_na([0, 2])); |
|
|
|
|
|
|
|
expect($b(any._(odd)._(_na([0, 2])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('any for matching item is True', () => { |
|
|
|
|
|
|
|
expect(any._(odd)).toDeferEvaluationOf(_na([0, 1, 2])); |
|
|
|
|
|
|
|
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(all._(even)).toDeferEvaluationOf(_na([])); |
|
|
|
|
|
|
|
expect($b(all._(even)._(_na([])))).toEqual(true); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('all for non-matching item is False', () => { |
|
|
|
|
|
|
|
expect(all._(even)).toDeferEvaluationOf(_na([0, 1, 2])); |
|
|
|
|
|
|
|
expect($b(all._(even)._(_na([0, 1, 2])))).toEqual(false); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('all for no non-matching item is True', () => { |
|
|
|
|
|
|
|
expect(all._(even)).toDeferEvaluationOf(_na([0, 2])); |
|
|
|
|
|
|
|
expect($b(all._(even)._(_na([0, 2])))).toEqual(true); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('handles infinite lists', () => { |
|
|
|
|
|
|
|
expect($b(all._(even)._(infinite))).toEqual(false); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|