List indexing

master
Freywar Ulvnaudgari 2 years ago
parent f19b0ebf01
commit 252e795a65
  1. 15
      src/list.ts
  2. 98
      test/list.spec.ts

@ -1,6 +1,7 @@
import { toNative as $$, L, P, _, fromNative as __, undef } from './core'; import { toNative as $$, L, P, _, fromNative as __, undef } from './core';
import { EQ, GT, LT, Ord, eq as eqc } from './ord'; import { EQ, GT, LT, Ord, eq as eqc } from './ord';
import { Bool, False, True, and, iif, or } from './bool'; import { Bool, False, True, and, iif, or } from './bool';
import { Num } from 'src/num';
export type List<T extends P> = L<<R extends P>(z: R) => L<(f: L<(x: T) => L<(xs: List<T>) => R>>) => R>>; export type List<T extends P> = L<<R extends P>(z: R) => L<(f: L<(x: T) => L<(xs: List<T>) => R>>) => R>>;
@ -99,6 +100,20 @@ export const all: L<<T extends P>(f: L<(x: T) => Bool>) => L<(xs: List<T>) => Bo
= _(<T extends P>(f: L<(x: T) => Bool>) => = _(<T extends P>(f: L<(x: T) => Bool>) =>
_((xs: List<T>) => xs._(True)._(_(x => _(xs => and._(f._(x))._(all._(f)._(xs))))))); _((xs: List<T>) => xs._(True)._(_(x => _(xs => and._(f._(x))._(all._(f)._(xs)))))));
export const get: L<<T extends P>(i: Num) => L<(xs: List<T>) => T>>
= _(<T extends P>(i: Num) =>
_((xs: List<T>) =>
xs._(undef)._(_((x: T) => _((xs: List<T>) => i._(x)._(_(pi => get._<T>(pi)._(xs))))))));
export const update: L<<T extends P>(f: L< (p: T) => T>) => L<(i: Num) => L<(xs: List<T>) => List<T>>>>
= _(<T extends P>(f: L< (p: T) => T>) =>
_((i: Num) =>
_((xs: List<T>) =>
xs._(undef)._(_(x => _(xs => i._(cons._(f._(x))._(xs))._(_(pi => cons._(x)._(update._(f)._(pi)._(xs))))))))));
export const set: L<<T extends P>(v: T) => L<(i: Num) => L<(xs: List<T>) => List<T>>>>
= _(<T extends P>(v: T) => update._<T>(_(_ => v)));
export const fromArray: <T extends P>(xs: T[]) => List<T> export const fromArray: <T extends P>(xs: T[]) => List<T>
= xs => xs.length === 0 ? Nil : Cons._(xs[0])._(new L(() => fromArray(xs.slice(1)).value)); = xs => xs.length === 0 ? Nil : Cons._(xs[0])._(new L(() => fromArray(xs.slice(1)).value));

@ -1,9 +1,9 @@
import { describe, expect, it } from '@jest/globals'; import { describe, expect, it } from '@jest/globals';
import { fromNative as $$, L, _, toNative as __, undef } from '../src/core'; import { toNative as $$, L, _, fromNative as __, undef } from '../src/core';
import { toNOrd as $o, NOrd } from '../src/ord'; import { toNOrd as $o, NOrd } from '../src/ord';
import { toBoolean as $b, iif } from '../src/bool'; 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 { 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'; 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';
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);
@ -13,7 +13,7 @@ describe('List', () => {
= xs => xs.length === 0 ? Nil : Cons._(_nn(xs[0]))._(new L(() => _na(xs.slice(1)).value)); = xs => xs.length === 0 ? Nil : Cons._(_nn(xs[0]))._(new L(() => _na(xs.slice(1)).value));
const $na: (xs: List<Num>) => number[] const $na: (xs: List<Num>) => number[]
= xs => __(xs._($$([]))._(_(x => _(xs => $$([$nn(x), ...$na(xs)]))))); = xs => $$(xs._(__([]))._(_(x => _(xs => __([$nn(x), ...$na(xs)])))));
describe('toArray', () => { describe('toArray', () => {
it('converts []', () => { it('converts []', () => {
@ -81,7 +81,7 @@ describe('List', () => {
describe('head', () => { describe('head', () => {
it('returns nothing from Nil', () => { it('returns nothing from Nil', () => {
expect(() => __(head._(Nil))).toThrow(); expect(() => $$(head._(Nil))).toThrow();
}); });
it('returns only item', () => { it('returns only item', () => {
@ -493,4 +493,94 @@ describe('List', () => {
expect($b(all._(even)._(infinite))).toEqual(false); expect($b(all._(even)._(infinite))).toEqual(false);
}); });
}); });
describe('get', () => {
it('returns nothing from Nil', () => {
expect(() => $n(get._(_n(0))._(Nil))).toThrow();
});
it('returns nothing with out of bounds index', () => {
expect(() => $n(get._(_n(100))._(_na([0, 1, 2, 3])))).toThrow();
});
it('[0, 1, 2, 3][0] is 0', () => {
expect($n(get._(_n(0))._(_na([0, 1, 2, 3])))).toBe(0);
});
it('[0, 1, 2, 3][1] is 1', () => {
expect($n(get._(_n(1))._(_na([0, 1, 2, 3])))).toBe(1);
});
it('[0, 1, 2, 3][2] is 2', () => {
expect($n(get._(_n(2))._(_na([0, 1, 2, 3])))).toBe(2);
});
it('[0, 1, 2, 3][3] get 3 is 3', () => {
expect($n(get._(_n(3))._(_na([0, 1, 2, 3])))).toBe(3);
});
it('handles infinite lists', () => {
expect($n(get._(_n(4))._(infinite))).toBe(4);
});
});
describe('set', () => {
it('can not update Nil', () => {
expect(() => $na(set._(_n(10))._(_n(0))._(Nil))).toThrow();
});
it('can not update out of bounds index', () => {
expect(() => $na(set._(_n(10))._(_n(100))._(_na([0, 1, 2, 3])))).toThrow();
});
it('[0, 1, 2, 3][0] = 10 is [10, 1, 2, 3]', () => {
expect($na(set._(_n(10))._(_n(0))._(_na([0, 1, 2, 3])))).toEqual([10, 1, 2, 3]);
});
it('[0, 1, 2, 3][1] = 10 is [0, 10, 2, 3]', () => {
expect($na(set._(_n(10))._(_n(1))._(_na([0, 1, 2, 3])))).toEqual([0, 10, 2, 3]);
});
it('[0, 1, 2, 3][2] = 10 is [0, 1, 10, 3]', () => {
expect($na(set._(_n(10))._(_n(2))._(_na([0, 1, 2, 3])))).toEqual([0, 1, 10, 3]);
});
it('[0, 1, 2, 3][3] = 10 is [0, 1, 2, 10]', () => {
expect($na(set._(_n(10))._(_n(3))._(_na([0, 1, 2, 3])))).toEqual([0, 1, 2, 10]);
});
it('handles infinite lists', () => {
expect($n(get._(_n(4))._(set._(_n(10))._(_n(4))._(infinite)))).toBe(10);
});
});
describe('update', () => {
it('can not update Nil', () => {
expect(() => $na(update._(succ)._(_n(0))._(Nil))).toThrow();
});
it('can not update out of bounds index', () => {
expect(() => $na(update._(succ)._(_n(100))._(_na([0, 1, 2, 3])))).toThrow();
});
it('[0, 1, 2, 3][0]++ is [10, 1, 2, 3]', () => {
expect($na(update._(succ)._(_n(0))._(_na([0, 1, 2, 3])))).toEqual([1, 1, 2, 3]);
});
it('[0, 1, 2, 3][1]++ is [0, 10, 2, 3]', () => {
expect($na(update._(succ)._(_n(1))._(_na([0, 1, 2, 3])))).toEqual([0, 2, 2, 3]);
});
it('[0, 1, 2, 3][2]++ is [0, 1, 10, 3]', () => {
expect($na(update._(succ)._(_n(2))._(_na([0, 1, 2, 3])))).toEqual([0, 1, 3, 3]);
});
it('[0, 1, 2, 3][3]++ is [0, 1, 2, 10]', () => {
expect($na(update._(succ)._(_n(3))._(_na([0, 1, 2, 3])))).toEqual([0, 1, 2, 4]);
});
it('handles infinite lists', () => {
expect($n(get._(_n(4))._(update._(succ)._(_n(4))._(infinite)))).toBe(5);
});
});
}); });

Loading…
Cancel
Save