parent
1ae5e491a5
commit
66666617e1
@ -0,0 +1,18 @@ |
||||
|
||||
import { L, _ } from './core'; |
||||
import { Bool } from './bool'; |
||||
import { toNumber as $n, Num, Zero, fromNumber as _n, eq as eqn } from './num'; |
||||
|
||||
export type Char = Num; |
||||
|
||||
export const Null: Char |
||||
= Zero; |
||||
|
||||
export const eq: L<(l: Char) => L<(r: Char) => Bool>> |
||||
= eqn; |
||||
|
||||
export const fromChar: (c: string) => Char |
||||
= c => _n(c.charCodeAt(0)); |
||||
|
||||
export const toChar: (c: Char) => string |
||||
= c => String.fromCharCode($n(c)); |
||||
@ -0,0 +1,31 @@ |
||||
import { L, P, _ } from './core'; |
||||
|
||||
export type Pair<F extends P, S extends P> = L<<R extends P>(f: L<(f: F) => L<(s: S) => R>>) => R>; |
||||
|
||||
export const Pair: L<<F extends P, S extends P>(f: F) => L<(s: S) => Pair<F, S>>> |
||||
= |
||||
_(<F extends P, S extends P>(f: F) => |
||||
_((s: S) => |
||||
_(<R extends P>(p: L<(f: F) => L<(s: S) => R>>) => p._(f)._(s)))); |
||||
|
||||
export const fst: L<<F extends P, S extends P>(p: Pair<F, S>) => F> |
||||
= _(p => p._(_(f => _(_s => f)))); |
||||
|
||||
export const snd: L<<F extends P, S extends P>(p: Pair<F, S>) => S> |
||||
= _(p => p._(_(_f => _(s => s)))); |
||||
|
||||
export const first: L<<F extends P, FR extends P, S extends P>(t: L<(f: F) => FR>) => L<(p: Pair<F, S>) => Pair<FR, S>>> |
||||
= |
||||
_(<F extends P, FR extends P>(t: L<(f: F) => FR>) => |
||||
_(<S extends P>(p: Pair<F, S>) => p._(_(f => _(s => Pair._(t._(f))._(s)))))); |
||||
|
||||
export const second: L<<F extends P, S extends P, SR extends P>(t: L<(s: S) => SR>) => L<(p: Pair<F, S>) => Pair<F, SR>>> |
||||
= |
||||
_(<S extends P, SR extends P>(t: L<(s: S) => SR>) => |
||||
_(<F extends P>(p: Pair<F, S>) => p._(_(f => _(s => Pair._(f)._(t._(s))))))); |
||||
|
||||
export const both: L<<F extends P, FR extends P, S extends P, SR extends P>(tf: L<(f: F) => FR>) => L<(ts: L<(s: S) => SR>) =>L<(p: Pair<F, S>) => Pair<FR, SR>>>> |
||||
= |
||||
_(<F extends P, FR extends P>(tf: L<(f: F) => FR>) => |
||||
_(<S extends P, SR extends P>(ts: L<(s: S) => SR>) => |
||||
_((p: Pair<F, S>) => p._(_(f => _(s => Pair._(tf._(f))._(ts._(s)))))))); |
||||
@ -0,0 +1,28 @@ |
||||
import { toNative as $n, L, _, fromNative as _n } from './core'; |
||||
import { Bool } from './bool'; |
||||
import { fromNumber as _nn } from './num'; |
||||
import { toChar as $c, Char, fromChar as _c, eq as eqc } from './char'; |
||||
import { Cons as ConsL, List, Nil, concat as concatl, eq as eql } from './list'; |
||||
|
||||
export type String = List<Char>; |
||||
|
||||
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 const eq: L<(l: String) => L<(r: String) => Bool>> |
||||
= eql._(eqc); |
||||
|
||||
export const fromString: (xs: string) => String |
||||
= xs => xs.length === 0 ? Nil : Cons._(_c(xs[0]))._(new L(() => fromString(xs.slice(1)).value)); |
||||
|
||||
export const toString: (xs: String) => string |
||||
= xs => $n(xs._(_n(''))._(_(x => _(xs => _n($c(x) + toString(xs)))))); |
||||
@ -0,0 +1,64 @@ |
||||
import { describe, expect, it } from '@jest/globals'; |
||||
import { toBoolean as $b, fromBoolean as _b } from '../src/bool'; |
||||
import { fromNumber as _n } from '../src/num'; |
||||
import { toChar as $, fromChar as _, eq } from '../src/char'; |
||||
|
||||
describe('Char', () => { |
||||
describe('toChar', () => { |
||||
it('converts "0"', () => { |
||||
expect($(_n(48))).toBe('0'); |
||||
}); |
||||
|
||||
it('converts "a"', () => { |
||||
expect($(_n(97))).toBe('a'); |
||||
}); |
||||
|
||||
it('converts "Z"', () => { |
||||
expect($(_n(90))).toBe('Z'); |
||||
}); |
||||
|
||||
it('converts "-"', () => { |
||||
expect($(_n(45))).toBe('-'); |
||||
}); |
||||
}); |
||||
|
||||
describe('fromChar', () => { |
||||
it('converts "0"', () => { |
||||
expect($(_('0'))).toBe('0'); |
||||
}); |
||||
|
||||
it('converts "a"', () => { |
||||
expect($(_('a'))).toBe('a'); |
||||
}); |
||||
|
||||
it('converts "Z"', () => { |
||||
expect($(_('Z'))).toBe('Z'); |
||||
}); |
||||
|
||||
it('converts "-"', () => { |
||||
expect($(_('-'))).toBe('-'); |
||||
}); |
||||
}); |
||||
|
||||
describe('eq', () => { |
||||
it('"0" eq "0" is True', () => { |
||||
expect(eq).toDeferEvaluationOf(_('0'), _('0')); |
||||
expect($b(eq._(_('0'))._(_('0')))).toBe(true); |
||||
}); |
||||
|
||||
it('"0" eq "a" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(_('0'), _('a')); |
||||
expect($b(eq._(_('0'))._(_('a')))).toBe(false); |
||||
}); |
||||
|
||||
it('"a" eq "a" is True', () => { |
||||
expect(eq).toDeferEvaluationOf(_('a'), _('a')); |
||||
expect($b(eq._(_('a'))._(_('a')))).toBe(true); |
||||
}); |
||||
|
||||
it('"a" eq "z" is True', () => { |
||||
expect(eq).toDeferEvaluationOf(_('a'), _('z')); |
||||
expect($b(eq._(_('a'))._(_('z')))).toBe(false); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,54 @@ |
||||
import { describe, expect, it } from '@jest/globals'; |
||||
import { undef } from '../src/core'; |
||||
import { toBoolean as $b, fromBoolean as _b, not } from '../src/bool'; |
||||
import { toNumber as $n, fromNumber as _n, succ } from '../src/num'; |
||||
import { Pair, both, first, fst, second, snd } from '../src/pair'; |
||||
|
||||
describe('Pair', () => { |
||||
describe('fst', () => { |
||||
it('returns first', () => { |
||||
expect($b(fst._(Pair._(_b(false))._(_n(0))))).toBe(false); |
||||
}); |
||||
|
||||
it('ignores second', () => { |
||||
expect($b(fst._(Pair._(_b(false))._(undef)))).toBe(false); |
||||
}); |
||||
}); |
||||
|
||||
describe('snd', () => { |
||||
it('returns second', () => { |
||||
expect($n(snd._(Pair._(_b(false))._(_n(0))))).toBe(0); |
||||
}); |
||||
|
||||
it('ignores first', () => { |
||||
expect($n(snd._(Pair._(undef)._(_n(0))))).toBe(0); |
||||
}); |
||||
}); |
||||
|
||||
describe('first', () => { |
||||
it('updates first', () => { |
||||
expect($b(fst._(first._(not)._(Pair._(_b(false))._(_n(0)))))).toBe(true); |
||||
}); |
||||
|
||||
it('ignores second', () => { |
||||
expect($b(fst._(first._(not)._(Pair._(_b(false))._(undef))))).toBe(true); |
||||
}); |
||||
}); |
||||
|
||||
describe('second', () => { |
||||
it('updates second', () => { |
||||
expect($n(snd._(second._(succ)._(Pair._(_b(false))._(_n(0)))))).toBe(1); |
||||
}); |
||||
|
||||
it('ignores first', () => { |
||||
expect($n(snd._(second._(succ)._(Pair._(undef)._(_n(0)))))).toBe(1); |
||||
}); |
||||
}); |
||||
|
||||
describe('both', () => { |
||||
it('updates both', () => { |
||||
expect($b(fst._(both._(not)._(succ)._(Pair._(_b(false))._(_n(0)))))).toBe(true); |
||||
expect($n(snd._(both._(not)._(succ)._(Pair._(_b(false))._(_n(0)))))).toBe(1); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,106 @@ |
||||
import { describe, expect, it } from '@jest/globals'; |
||||
import { L, _, undef } from '../src/core'; |
||||
import { toBoolean as $b } from '../src/bool'; |
||||
import { toChar as $c, fromChar as _c, eq as eqc } from '../src/char'; |
||||
import { toString as $s, Cons, Empty, String, fromString as _s, concat, eq } from '../src/string'; |
||||
|
||||
describe('String', () => { |
||||
const infinite: String = new L(() => Cons._(_c('a'))._(infinite).value);; |
||||
|
||||
describe('toString', () => { |
||||
it('converts ""', () => { |
||||
expect($s(Empty)).toBe(''); |
||||
}); |
||||
|
||||
it('converts "a"', () => { |
||||
expect($s(Cons._(_c('a'))._(Empty))).toBe('a'); |
||||
}); |
||||
|
||||
it('converts "abc"', () => { |
||||
expect($s(Cons._(_c('a'))._(Cons._(_c('b'))._(Cons._(_c('c'))._(Empty))))).toBe('abc'); |
||||
}); |
||||
}); |
||||
|
||||
describe('fromString', () => { |
||||
it('converts ""', () => { |
||||
expect($s(_s(''))).toBe(''); |
||||
}); |
||||
|
||||
it('converts "a"', () => { |
||||
expect($s(_s('a'))).toBe('a'); |
||||
}); |
||||
|
||||
it('converts "2"', () => { |
||||
expect($s(_s('abc'))).toBe('abc'); |
||||
}); |
||||
}); |
||||
|
||||
describe('concat', () => { |
||||
it('"" concat "" is ""', () => { |
||||
expect(concat).toDeferEvaluationOf(Empty, Empty); |
||||
expect($s(concat._(Empty)._(Empty))).toBe(''); |
||||
}); |
||||
|
||||
it('"a" concat "b" is "ab"', () => { |
||||
expect(concat).toDeferEvaluationOf(_s('a'), _s('b')); |
||||
expect($s(concat._(_s('a'))._(_s('b')))).toBe('ab'); |
||||
}); |
||||
|
||||
it('"abc" concat "def" is "abcdef"', () => { |
||||
expect(concat).toDeferEvaluationOf(_s('abc'), _s('def')); |
||||
expect($s(concat._(_s('abc'))._(_s('def')))).toBe('abcdef'); |
||||
}); |
||||
|
||||
it('handles infinite lists', () => { |
||||
expect($c(concat._(infinite)._(infinite)._(undef)._(_(x => _(_xs => x))))).toBe('a'); |
||||
}); |
||||
}); |
||||
|
||||
describe('eq', () => { |
||||
it('"" eq "" is True', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s(''), _s('')); |
||||
expect($b(eq._(_s(''))._(_s('')))).toBe(true); |
||||
}); |
||||
|
||||
it('"" eq "abc" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s(''), _s("abc")); |
||||
expect($b(eq._(_s(''))._(_s("abc")))).toBe(false); |
||||
}); |
||||
|
||||
it('"abc" eq "" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s("abc"), _s('')); |
||||
expect($b(eq._(_s("abc"))._(_s('')))).toBe(false); |
||||
}); |
||||
|
||||
it('"a" eq "abc" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s('a'), _s("abc")); |
||||
expect($b(eq._(_s('a'))._(_s("abc")))).toBe(false); |
||||
}); |
||||
|
||||
it('"abc" eq "a" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s("abc"), _s('a')); |
||||
expect($b(eq._(_s("abc"))._(_s('a')))).toBe(false); |
||||
}); |
||||
|
||||
|
||||
it('"bca" eq "abc" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s("bca"), _s("abc")); |
||||
expect($b(eq._(_s("bca"))._(_s("abc")))).toBe(false); |
||||
}); |
||||
|
||||
it('"abc" eq "bca" is False', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s("abc"), _s("bca")); |
||||
expect($b(eq._(_s("abc"))._(_s("bca")))).toBe(false); |
||||
}); |
||||
|
||||
it('"abc" eq "abc" is True', () => { |
||||
expect(eq).toDeferEvaluationOf(eqc, _s("abc"), _s("abc")); |
||||
expect($b(eq._(_s("abc"))._(_s("abc")))).toBe(true); |
||||
}); |
||||
|
||||
it('handles infinite lists', () => { |
||||
expect($b(eq._(infinite)._(_s("abc")))).toBe(false); |
||||
expect($b(eq._(_s("abc"))._(infinite))).toBe(false); |
||||
}); |
||||
}); |
||||
}); |
||||
Loading…
Reference in new issue