From 084399c6b46ffbf672d1b7b952a5afd52c7d6371 Mon Sep 17 00:00:00 2001 From: Freywar Ulvnaudgari Date: Thu, 22 Aug 2024 23:36:51 +0300 Subject: [PATCH] Strict lambda parameters --- src/bf.ts | 52 +++++++++++++++++++-------------------- src/bool.show.ts | 4 +-- src/bool.ts | 26 ++++++++++---------- src/byte.ts | 12 ++++----- src/char.show.ts | 4 +-- src/core.ts | 29 ++++++---------------- src/list.show.ts | 4 +-- src/list.ts | 60 ++++++++++++++++++++++----------------------- src/log.ts | 4 +-- src/num.show.ts | 4 +-- src/num.ts | 38 ++++++++++++++-------------- src/ord.show.ts | 4 +-- src/ord.ts | 16 ++++++------ src/pair.show.ts | 4 +-- src/pair.ts | 28 ++++++++++----------- src/string.ts | 6 ++--- test/list.spec.ts | 18 +++++++------- test/num.spec.ts | 4 +-- test/string.spec.ts | 8 +++--- 19 files changed, 156 insertions(+), 169 deletions(-) diff --git a/src/bf.ts b/src/bf.ts index 9114a3e..6a89abf 100644 --- a/src/bf.ts +++ b/src/bf.ts @@ -1,4 +1,4 @@ -import { _, cnst, g, id, l, n, pipe, r } from './core'; +import { _, _l, cnst, g, id, n, pipe, _r } from './core'; import { iif } from './bool'; import { Zero, ge, ifz, pred, succ } from './num'; import { x00 } from './byte'; @@ -9,50 +9,50 @@ import { Empty, get, len, snoc } from './string'; n('bf'); -const done = g('done', uncurry._(l('p', cnst._(uncurry._(l('is', l('cs', ge._(head._('is'))._(len._('cs')))))._('p'))))); +const done = g('done', uncurry._(_l(p => cnst._(uncurry._(_l(is => _l(cs => ge._(head._(is))._(len._(cs)))))._(p))))); -const command = g('command', l('c', uncurry._(l('p', cnst._(eq._('c')._(uncurry._(pipe._(get)._(head))._('p'))))))); +const command = g('command', _l(c => uncurry._(_l(p => cnst._(eq._(c)._(uncurry._(pipe._(get)._(head))._(p))))))); const advance = g('advance', first._(first._(update._(succ)._(Zero)))); -const save = g('save', first._(first._(l('is', cons._(head._('is'))._('is'))))); +const save = g('save', first._(first._(_l(is => cons._(head._(is))._(is))))); const restore = g('restore', first._(first._(tail))); -const reset = g('reset', first._(first._(l('is', cons._(head._('is'))._(tail._(tail._('is'))))))); +const reset = g('reset', first._(first._(_l(is => cons._(head._(is))._(tail._(tail._(is))))))); -const inc = g('inc', second._(first._(l('t', second._(update._(cinc)._(fst._('t')))._('t'))))); +const inc = g('inc', second._(first._(_l(t => second._(update._(cinc)._(fst._(t)))._(t))))); -const dec = g('dec', second._(first._(l('t', second._(update._(cdec)._(fst._('t')))._('t'))))); +const dec = g('dec', second._(first._(_l(t => second._(update._(cdec)._(fst._(t)))._(t))))); const read = g('read', pipe._(pipe._(uncurry._(get))._(fst))._(snd)); -const input = g('input', second._(uncurry._(l('t', l('io', Pair._(second._(set._(head._(fst._('io')))._(fst._('t')))._('t'))._(first._(tail)._('io'))))))); +const input = g('input', second._(uncurry._(_l(t => _l(io => Pair._(second._(set._(head._(fst._(io)))._(fst._(t)))._(t))._(first._(tail)._(io))))))); -const output = g('output', second._(uncurry._(l('t', pipe._(Pair._('t'))._(second._(l('os', snoc._('os')._(uncurry._(get)._('t'))))))))); +const output = g('output', second._(uncurry._(_l(t => pipe._(Pair._(t))._(second._(_l(os => snoc._(os)._(uncurry._(get)._(t))))))))); const next = g('next', second._(first._(first._(succ)))); const prev = g('prev', second._(first._(first._(pred)))); -const jump = g('jump', l('d', l('s', - iif._(command._(_c('['))._('s'))._(r('bf', 'jump')._(succ._('d'))) - ._(iif._(command._(_c(']'))._('s'))._(ifz._(pred._('d'))._(cnst._('s'))._(r('bf', 'jump')._(pred._('d')))) - ._(r('bf', 'jump')._('d')))._(advance._('s'))))); +const jump = g('jump', _l(d => _l(s => + iif._(command._(_c('['))._(s))._(_r('bf', 'jump')._(succ._(d))) + ._(iif._(command._(_c(']'))._(s))._(ifz._(pred._(d))._(cnst._(s))._(_r('bf', 'jump')._(pred._(d)))) + ._(_r('bf', 'jump')._(d)))._(advance._(s))))); -const whlnz = g('whlnz', l('s', ifn._(read._('s'))._(jump._(Zero))._(save)._('s'))); +const whlnz = g('whlnz', _l(s => ifn._(read._(s))._(jump._(Zero))._(save)._(s))); -const endwhl = g('endwhl', l('s', ifn._(read._('s'))._(reset)._(pipe._(save)._(restore))._('s'))); +const endwhl = g('endwhl', _l(s => ifn._(read._(s))._(reset)._(pipe._(save)._(restore))._(s))); -const exec = g('exec', l('s', iif._(done._('s'))._('s')._(r('bf', 'exec')._(advance - ._(iif._(command._(_c('>'))._('s'))._(next) - ._(iif._(command._(_c('<'))._('s'))._(prev) - ._(iif._(command._(_c('+'))._('s'))._(inc) - ._(iif._(command._(_c('-'))._('s'))._(dec) - ._(iif._(command._(_c('.'))._('s'))._(output) - ._(iif._(command._(_c(','))._('s'))._(input) - ._(iif._(command._(_c('['))._('s'))._(whlnz) - ._(iif._(command._(_c(']'))._('s'))._(endwhl) - ._(id))))))))._('s')))))); +const exec = g('exec', _l(s => iif._(done._(s))._(s)._(_r('bf', 'exec')._(advance + ._(iif._(command._(_c('>'))._(s))._(next) + ._(iif._(command._(_c('<'))._(s))._(prev) + ._(iif._(command._(_c('+'))._(s))._(inc) + ._(iif._(command._(_c('-'))._(s))._(dec) + ._(iif._(command._(_c('.'))._(s))._(output) + ._(iif._(command._(_c(','))._(s))._(input) + ._(iif._(command._(_c('['))._(s))._(whlnz) + ._(iif._(command._(_c(']'))._(s))._(endwhl) + ._(id))))))))._(s)))))); -export const run = g('run', l('p', l('i', snd._(snd._(snd._(exec._(Pair._(Pair._(singleton._(Zero))._('p'))._(Pair._(Pair._(Zero)._(repeat._(x00)))._(Pair._('i')._(Empty)))))))))); +export const run = g('run', _l(p => _l(i => snd._(snd._(snd._(exec._(Pair._(Pair._(singleton._(Zero))._(p))._(Pair._(Pair._(Zero)._(repeat._(x00)))._(Pair._(i)._(Empty)))))))))); diff --git a/src/bool.show.ts b/src/bool.show.ts index 19d78a0..0f3d2b3 100644 --- a/src/bool.show.ts +++ b/src/bool.show.ts @@ -1,7 +1,7 @@ -import { g, l, n } from './core'; +import { _l, g, n } from './core'; import { iif } from './bool'; import { fromString as _s } from './string'; n('bool.show'); -export const show = g('show', l('b', iif._('b')._(_s('True'))._(_s('False')))); +export const show = g('show', _l(b => iif._(b)._(_s('True'))._(_s('False')))); diff --git a/src/bool.ts b/src/bool.ts index 245010d..2b0289a 100644 --- a/src/bool.ts +++ b/src/bool.ts @@ -1,33 +1,33 @@ -import { $, Term, _, g, id, l, n, pipe, r } from './core'; +import { $, Term, _, _l, g, id, n, pipe } from './core'; import { EQ, GT, LT } from './ord'; n('bool'); -export const True = g('True', l('t', l('_', 't'))); +export const True = g('True', _l(t => _l(_ => t))); -export const False = g('False', l('_', l('f', 'f'))); +export const False = g('False', _l(_ => _l(f => f))); export const iif = g('iif', id); -export const not = g('not', l('b', r('b')._(False)._(True))); +export const not = g('not', _l(b => b._(False)._(True))); -export const cmp = g('cmp', l('l', l('r', r('l')._(r('r')._(EQ)._(GT))._(r('r')._(LT)._(EQ))))); +export const cmp = g('cmp', _l(l => _l(r => l._(r._(EQ)._(GT))._(r._(LT)._(EQ))))); -export const lt = g('lt', l('l', r('l')._(False))); +export const lt = g('lt', _l(l => l._(False))); -export const le = g('le', l('l', not._('l')._(True))); +export const le = g('le', _l(l => not._(l)._(True))); -export const eq = g('eq', l('l', l('r', r('l')._('r')._(not._('r'))))); +export const eq = g('eq', _l(l => _l(r => l._(r)._(not._(r))))); -export const ge = g('ge', l('l', pipe._(not)._(lt._('l')))); +export const ge = g('ge', _l(l => pipe._(not)._(lt._(l)))); -export const gt = g('gt', l('l', pipe._(not)._(le._('l')))); +export const gt = g('gt', _l(l => pipe._(not)._(le._(l)))); -export const and = g('and', l('l', not._('l')._(False))); +export const and = g('and', _l(l => not._(l)._(False))); -export const or = g('or', l('l', r('l')._(True))); +export const or = g('or', _l(l => l._(True))); -export const xor = g('xor', l('l', l('r', r('l')._(not._('r'))._('r')))); +export const xor = g('xor', _l(l => _l(r => l._(not._(r))._(r)))); export const fromBoolean: (b: boolean) => Term = b => b ? True : False; diff --git a/src/byte.ts b/src/byte.ts index 0d73e6e..ebe2838 100644 --- a/src/byte.ts +++ b/src/byte.ts @@ -1,4 +1,4 @@ -import { Term, _, g, id, l, n, r } from './core'; +import { Term, _, _l, g, id, n, _r as ref } from './core'; import { iif } from './bool'; import { Succ, Zero, fromNumber as _n, eq } from './num'; @@ -8,18 +8,18 @@ export const x00 = g('x00', Zero); export const xFF = g('xFF', _n(255)); -export const Inc = g('Inc', l('p', iif._(eq._(xFF)._('p'))._(x00)._(Succ._('p')))); +export const Inc = g('Inc', _l(p => iif._(eq._(xFF)._(p))._(x00)._(Succ._(p)))); export { ifz, cmp, lt, le, eq, ge, gt, even, odd, div, mod, toNumber } from './num'; export const inc = g('inc', Inc); -export const dec = g('dec', l('n', r('n')._(xFF)._(id))); +export const dec = g('dec', _l(n => n._(xFF)._(id))); -export const sum = g('sum', l('l', l('r', r('r')._('l')._(r('byte', 'sum')._(inc._('l')))))); +export const sum = g('sum', _l(l => _l(r => r._(l)._(ref('byte', 'sum')._(inc._(l)))))); -export const sub = g('sub', l('l', l('r', r('r')._('l')._(r('byte', 'sub')._(dec._('l')))))); +export const sub = g('sub', _l(l => _l(r => r._(l)._(ref('byte', 'sub')._(dec._(l)))))); -export const mul = g('mul', l('l', l('r', r('l')._(x00)._(l('pl', sum._('r')._(r('byte', 'mul')._('pl')._('r'))))))); +export const mul = g('mul', _l(l => _l(r => l._(x00)._(_l(pl => sum._(r)._(ref('byte', 'mul')._(pl)._(r))))))); export const fromNumber: (n: number) => Term = n => _n(n % 256); diff --git a/src/char.show.ts b/src/char.show.ts index c722b04..aa0f04b 100644 --- a/src/char.show.ts +++ b/src/char.show.ts @@ -1,7 +1,7 @@ -import { g, l, n, pipe } from './core'; +import { _l, g, n, pipe } from './core'; import { singleton } from './list'; import { fromString as _s, wrap } from './string'; n('char.show'); -export const show = g('show', l('c', pipe._(wrap._(_s('\'')))._(singleton)._('c'))); +export const show = g('show', _l(c => pipe._(wrap._(_s('\'')))._(singleton)._(c))); diff --git a/src/core.ts b/src/core.ts index adb2aa1..819a5b6 100644 --- a/src/core.ts +++ b/src/core.ts @@ -50,11 +50,8 @@ export abstract class Term { return `${this.context()} ${this.expression()}`; } - public _(arg: Term): Term; - public _(name: string): Term; - public _(namespace: string, name: string): Term; - public _(argOrNamespace: Term | string, maybeName?: string): Term { - return new Call(this, termify(argOrNamespace as string, maybeName as string)); + public _(arg: Term): Term { + return new Call(this, arg); } public toString(): string { @@ -73,7 +70,7 @@ type Termify = { }; const termify: Termify = (termOrNameOrNamespace: Term | string, maybeName?: string) => - typeof termOrNameOrNamespace === 'string' ? r(termOrNameOrNamespace as string, maybeName as string) : termOrNameOrNamespace; + typeof termOrNameOrNamespace === 'string' ? _r(termOrNameOrNamespace as string, maybeName as string) : termOrNameOrNamespace; export class Undef extends Term { constructor() { super(); } @@ -284,19 +281,9 @@ export const g = (name: string, term: Term) => { return new Ref(namespace, name); }; -type Refify = { - (name: string): Ref - (namespace: string, name: string): Ref -}; - -export const r: Refify = (namespaceOrName: string, name?: string) => new Ref(name ? namespaceOrName : 'local', name ?? namespaceOrName); - -type Lambdify = { - (param: string, body: Term): Lambda - (param: string, ref: string): Lambda -}; +export const _r = (ns: string, name: string) => new Ref(ns, name); -export const l: Lambdify = (param: string, body: Term | string): Lambda => new Lambda(param, termify(body as string)); +export const _l = (f: (p: Ref) => Term) => new Lambda(f.toString().split(' ')[0], f(new Ref('local', f.toString().split(' ')[0]))); type Deferedify = { (value: (bindings: Record) => Term): Deferred @@ -311,6 +298,6 @@ export const $ = (t: Term): T => { export const undef = g('undef', new Undef()); -export const id = g('id', l('f', 'f')); -export const cnst = g('cnst', l('x', l('_', 'x'))); -export const pipe = g('pipe', l('f', l('g', l('x', r('f')._(r('g')._('x')))))); +export const id = g('id', _l(f => f)); +export const cnst = g('cnst', _l(x => _l(_ => x))); +export const pipe = g('pipe', _l(f => _l(g => _l(x => f._(g._(x)))))); diff --git a/src/list.show.ts b/src/list.show.ts index 0c80749..e593cba 100644 --- a/src/list.show.ts +++ b/src/list.show.ts @@ -1,7 +1,7 @@ -import { _, g, l, n } from './core'; +import { _, _l, g, n } from './core'; import { concat, intersperse, map } from './list'; import { fromString as _s, cons, snoc } from './string'; n('list.show'); -export const show = g('show', l('eshow', l('xs', concat._(snoc._(cons._(_s('['))._(intersperse._(_s(', '))._(map._('eshow')._('xs'))))._(_s(']')))))); +export const show = g('show', _l(eshow => _l(xs => concat._(snoc._(cons._(_s('['))._(intersperse._(_s(', '))._(map._(eshow)._(xs))))._(_s(']')))))); diff --git a/src/list.ts b/src/list.ts index d580ba5..e919403 100644 --- a/src/list.ts +++ b/src/list.ts @@ -1,72 +1,72 @@ -import { $, Term, _, cnst, g, id, l, n, pipe, r, undef } from './core'; +import { $, Term, _, _l, cnst, g, id, n, pipe, _r as ref, undef } from './core'; import { EQ, GT, LT, eq as eqc } from './ord'; import { False, True, and, iif, or } from './bool'; import { Zero, succ } from './num'; n('list'); -export const Nil = g('Nil', l('z', l('_', 'z'))); +export const Nil = g('Nil', _l(z => _l(_ => z))); -export const Cons = g('Cons', l('x', l('xs', l('_', l('f', r('f')._('x')._('xs')))))); +export const Cons = g('Cons', _l(x => _l(xs => _l(_ => _l(f => f._(x)._(xs)))))); export const cons = g('cons', Cons); -export const snoc = g('snoc', l('xs', l('x', r('xs')._(cons._('x')._(Nil))._(l('y', l('ys', cons._('y')._(r('list', 'snoc')._('ys')._('x')))))))); +export const snoc = g('snoc', _l(xs => _l(x => xs._(cons._(x)._(Nil))._(_l(y => _l(ys => cons._(y)._(ref('list', 'snoc')._(ys)._(x)))))))); -export const nul = g('nul', l('xs', r('xs')._(True)._(cnst._(cnst._(False))))); +export const nul = g('nul', _l(xs => xs._(True)._(cnst._(cnst._(False))))); -export const len = g('len', l('xs', r('xs')._(Zero)._(cnst._(pipe._(succ)._(r('list', 'len')))))); +export const len = g('len', _l(xs => xs._(Zero)._(cnst._(pipe._(succ)._(ref('list', 'len')))))); -export const singleton = g('singleton', l('x', cons._('x')._(Nil))); +export const singleton = g('singleton', _l(x => cons._(x)._(Nil))); -export const append = g('append', l('l', l('r', r('l')._('r')._(l('x', l('xs', cons._('x')._(r('list', 'append')._('xs')._('r')))))))); +export const append = g('append', _l(l => _l(r => l._(r)._(_l(x => _l(xs => cons._(x)._(ref('list', 'append')._(xs)._(r)))))))); -export const concat = g('concat', l('ls', r('ls')._(Nil)._(l('x', pipe._(append._('x'))._(r('list', 'concat')))))); +export const concat = g('concat', _l(ls => ls._(Nil)._(_l(x => pipe._(append._(x))._(ref('list', 'concat')))))); -export const repeat = g('repeat', l('x', cons._('x')._(r('list', 'repeat')._('x')))); +export const repeat = g('repeat', _l(x => cons._(x)._(ref('list', 'repeat')._(x)))); -export const iterate = g('iterate', l('f', l('x', cons._('x')._(r('list', 'iterate')._('f')._(r('f')._('x')))))); +export const iterate = g('iterate', _l(f => _l(x => cons._(x)._(ref('list', 'iterate')._(f)._(f._(x)))))); -export const head = g('head', l('xs', r('xs')._(undef)._(cnst))); +export const head = g('head', _l(xs => xs._(undef)._(cnst))); -export const tail = g('tail', l('xs', r('xs')._(undef)._(cnst._(id)))); +export const tail = g('tail', _l(xs => xs._(undef)._(cnst._(id)))); -export const foldl = g('foldl', l('f', l('z', l('xs', r('xs')._('z')._(pipe._(r('list', 'foldl')._('f'))._(r('f')._('z'))))))); +export const foldl = g('foldl', _l(f => _l(z => _l(xs => xs._(z)._(pipe._(ref('list', 'foldl')._(f))._(f._(z))))))); -export const foldlz = g('foldlz', l('f', l('xs', r('xs')._(undef)._(foldl._('f'))))); +export const foldlz = g('foldlz', _l(f => _l(xs => xs._(undef)._(foldl._(f))))); -export const foldr = g('foldr', l('f', l('z', l('xs', r('xs')._('z')._(l('x', pipe._(r('f')._('x'))._(r('list', 'foldr')._('f')._('z')))))))); +export const foldr = g('foldr', _l(f => _l(z => _l(xs => xs._(z)._(_l(x => pipe._(f._(x))._(ref('list', 'foldr')._(f)._(z)))))))); export const foldrz = g('foldrz', undef); -export const cmp = g('cmp', l('ecmp', l('l', l('r', r('l')._(r('r')._(EQ)._(cnst._(cnst._(LT))))._(l('lx', l('lxs', r('r')._(GT)._(l('rx', l('rxs', iif._(eqc._(EQ)._(r('ecmp')._('lx')._('rx')))._(r('list', 'cmp')._('ecmp')._('lxs')._('rxs'))._(r('ecmp')._('lx')._('rx')))))))))))); +export const cmp = g('cmp', _l(ecmp => _l(l => _l(r => l._(r._(EQ)._(cnst._(cnst._(LT))))._(_l(lx => _l(lxs => r._(GT)._(_l(rx => _l(rxs => iif._(eqc._(EQ)._(ecmp._(lx)._(rx)))._(ref('list', 'cmp')._(ecmp)._(lxs)._(rxs))._(ecmp._(lx)._(rx)))))))))))); -export const lt = g('lt', l('ecmp', l('l', l('r', r('r')._(False)._(l('rx', l('rxs', r('l')._(True)._(l('lx', l('lxs', r('ecmp')._('lx')._('rx')._(True)._(r('list', 'lt')._('ecmp')._('lxs')._('rxs'))._(False))))))))))); +export const lt = g('lt', _l(ecmp => _l(l => _l(r => r._(False)._(_l(rx => _l(rxs => l._(True)._(_l(lx => _l(lxs => ecmp._(lx)._(rx)._(True)._(ref('list', 'lt')._(ecmp)._(lxs)._(rxs))._(False))))))))))); -export const le = g('le', l('ecmp', l('l', l('r', r('l')._(True)._(l('lx', l('lxs', r('r')._(False)._(l('rx', l('rxs', r('ecmp')._('lx')._('rx')._(True)._(r('list', 'le')._('ecmp')._('lxs')._('rxs'))._(False))))))))))); +export const le = g('le', _l(ecmp => _l(l => _l(r => l._(True)._(_l(lx => _l(lxs => r._(False)._(_l(rx => _l(rxs => ecmp._(lx)._(rx)._(True)._(ref('list', 'le')._(ecmp)._(lxs)._(rxs))._(False))))))))))); -export const eq = g('eq', l('eeq', l('l', l('r', r('l')._(r('r')._(True)._(cnst._(cnst._(False))))._(l('lx', l('lxs', r('r')._(False)._(l('rx', l('rxs', and._(r('eeq')._('lx')._('rx'))._(r('list', 'eq')._('eeq')._('lxs')._('rxs')))))))))))); +export const eq = g('eq', _l(eeq => _l(l => _l(r => l._(r._(True)._(cnst._(cnst._(False))))._(_l(lx => _l(lxs => r._(False)._(_l(rx => _l(rxs => and._(eeq._(lx)._(rx))._(ref('list', 'eq')._(eeq)._(lxs)._(rxs)))))))))))); -export const ge = g('ge', l('ecmp', l('l', l('r', r('r')._(True)._(l('rx', l('rxs', r('l')._(False)._(l('lx', l('lxs', r('ecmp')._('lx')._('rx')._(False)._(r('list', 'ge')._('ecmp')._('lxs')._('rxs'))._(True))))))))))); +export const ge = g('ge', _l(ecmp => _l(l => _l(r => r._(True)._(_l(rx => _l(rxs => l._(False)._(_l(lx => _l(lxs => ecmp._(lx)._(rx)._(False)._(ref('list', 'ge')._(ecmp)._(lxs)._(rxs))._(True))))))))))); -export const gt = g('gt', l('ecmp', l('l', l('r', r('l')._(False)._(l('lx', l('lxs', r('r')._(True)._(l('rx', l('rxs', r('ecmp')._('lx')._('rx')._(False)._(r('list', 'gt')._('ecmp')._('lxs')._('rxs'))._(True))))))))))); +export const gt = g('gt', _l(ecmp => _l(l => _l(r => l._(False)._(_l(lx => _l(lxs => r._(True)._(_l(rx => _l(rxs => ecmp._(lx)._(rx)._(False)._(ref('list', 'gt')._(ecmp)._(lxs)._(rxs))._(True))))))))))); -export const map = g('map', l('f', l('xs', r('xs')._(Nil)._(l('x', pipe._(cons._(r('f')._('x')))._(r('list', 'map')._('f'))))))); +export const map = g('map', _l(f => _l(xs => xs._(Nil)._(_l(x => pipe._(cons._(f._(x)))._(ref('list', 'map')._(f))))))); -export const filter = g('filter', l('f', l('xs', r('xs')._(Nil)._(l('x', pipe._(iif._(r('f')._('x'))._(cons._('x'))._(id))._(r('list', 'filter')._('f'))))))); +export const filter = g('filter', _l(f => _l(xs => xs._(Nil)._(_l(x => pipe._(iif._(f._(x))._(cons._(x))._(id))._(ref('list', 'filter')._(f))))))); -export const any = g('any', l('f', l('xs', r('xs')._(False)._(l('x', pipe._(or._(r('f')._('x')))._(r('list', 'any')._('f'))))))); +export const any = g('any', _l(f => _l(xs => xs._(False)._(_l(x => pipe._(or._(f._(x)))._(ref('list', 'any')._(f))))))); -export const all = g('all', l('f', l('xs', r('xs')._(True)._(l('x', pipe._(and._(r('f')._('x')))._(r('list', 'all')._('f'))))))); +export const all = g('all', _l(f => _l(xs => xs._(True)._(_l(x => pipe._(and._(f._(x)))._(ref('list', 'all')._(f))))))); -export const get = g('get', l('i', l('xs', r('xs')._(undef)._(l('x', r('i')._(cnst._('x'))._('list', 'get')))))); +export const get = g('get', _l(i => _l(xs => xs._(undef)._(_l(x => i._(cnst._(x))._(ref('list', 'get'))))))); -export const update = g('update', l('f', l('i', l('xs', r('xs')._(undef)._(l('x', l('xs', r('i')._(cons._(r('f')._('x'))._('xs'))._(l('pi', cons._('x')._(r('list', 'update')._('f')._('pi')._('xs'))))))))))); +export const update = g('update', _l(f => _l(i => _l(xs => xs._(undef)._(_l(x => _l(xs => i._(cons._(f._(x))._(xs))._(_l(pi => cons._(x)._(ref('list', 'update')._(f)._(pi)._(xs))))))))))); export const set = g('set', pipe._(update)._(cnst)); -export const intersperse = g('intersperse', l('v', l('xs', r('xs')._('xs')._(l('x', l('rxs', r('rxs')._('xs')._(cnst._(cnst._(cons._('x')._(cons._('v')._(r('list', 'intersperse')._('v')._('rxs')))))))))))); +export const intersperse = g('intersperse', _l(v => _l(xs => xs._(xs)._(_l(x => _l(rxs => rxs._(xs)._(cnst._(cnst._(cons._(x)._(cons._(v)._(ref('list', 'intersperse')._(v)._(rxs)))))))))))); export const fromArray: (xs: Term[]) => Term = xs => !xs.length ? Nil : Cons._(xs[0])._(_(() => fromArray(xs.slice(1)))); -export const toArray: (xs: Term) => Term[] = xs => $(xs._(_([]))._(l('x', l('xs', _(({ x, xs }) => _([x, ...toArray(xs)])))))); +export const toArray: (xs: Term) => Term[] = xs => $(xs._(_([]))._(_l(x => _l(xs => _(({ x, xs }) => _([x, ...toArray(xs)])))))); diff --git a/src/log.ts b/src/log.ts index c1f9b28..8b53c7c 100644 --- a/src/log.ts +++ b/src/log.ts @@ -1,7 +1,7 @@ -import { _, l } from './core'; +import { _, _l } from './core'; import { toString } from './string'; -export const log = l('s', l('p', _(({ s, p }) => { +export const log = _l(s => _l(p => _(({ s, p }) => { console.log(toString(s)); return p; }))); diff --git a/src/num.show.ts b/src/num.show.ts index 437c55e..c7faa04 100644 --- a/src/num.show.ts +++ b/src/num.show.ts @@ -1,8 +1,8 @@ -import { _, g, l, n, r } from './core'; +import { _, _l, g, n, _r } from './core'; import { iif } from './bool'; import { fromNumber as _n, div, lt, mod, sum } from './num'; import { Empty, append, cons } from './string'; n('num.show'); -export const show = g('show', l('n', iif._(lt._('n')._(_n(10)))._(cons._(sum._('n')._(_n(48)))._(Empty))._(append._(r('num.show', 'show')._(div._('n')._(_n(10))))._(r('num.show', 'show')._(mod._('n')._(_n(10))))))); +export const show = g('show', _l(n => iif._(lt._(n)._(_n(10)))._(cons._(sum._(n)._(_n(48)))._(Empty))._(append._(_r('num.show', 'show')._(div._(n)._(_n(10))))._(_r('num.show', 'show')._(mod._(n)._(_n(10))))))); diff --git a/src/num.ts b/src/num.ts index 336181b..3aa3674 100644 --- a/src/num.ts +++ b/src/num.ts @@ -1,45 +1,45 @@ -import { $, Term, _, cnst, g, id, l, n, pipe, r } from './core'; +import { $, Term, _, _l, cnst, g, id, n, pipe, _r as ref } from './core'; import { EQ, GT, LT } from './ord'; import { False, True, iif } from './bool'; n('num'); -export const Zero = g('Zero', l('z', l('_n', 'z'))); +export const Zero = g('Zero', _l(z => _l(_n => z))); -export const Succ = g('Succ', l('p', l('_z', l('n', r('n')._('p'))))); +export const Succ = g('Succ', _l(p => _l(_z => _l(n => n._(p))))); -export const ifz = g('ifz', l('n', l('t', l('f', r('n')._('t')._(cnst._('f')))))); +export const ifz = g('ifz', _l(n => _l(t => _l(f => n._(t)._(cnst._(f)))))); export const succ = g('succ', Succ); -export const pred = g('pred', l('n', r('n')._(Zero)._(id))); +export const pred = g('pred', _l(n => n._(Zero)._(id))); -export const cmp = g('cmp', l('l', l('r', r('l')._(r('r')._(EQ)._(cnst._(LT)))._(pipe._(r('r')._(GT))._('num', 'cmp'))))); +export const cmp = g('cmp', _l(l => _l(r => l._(r._(EQ)._(cnst._(LT)))._(pipe._(r._(GT))._(ref('num', 'cmp')))))); -export const lt = g('lt', l('l', l('r', r('r')._(False)._(r('l')._(cnst._(True))._('num', 'lt'))))); +export const lt = g('lt', _l(l => _l(r => r._(False)._(l._(cnst._(True))._(ref('num', 'lt')))))); -export const le = g('le', l('l', l('r', r('l')._(True)._(r('r')._(cnst._(False))._('num', 'ge'))))); +export const le = g('le', _l(l => _l(r => l._(True)._(r._(cnst._(False))._(ref('num', 'ge')))))); -export const eq = g('eq', l('l', l('r', r('l')._(r('r')._(True)._(cnst._(False)))._(r('r')._(cnst._(False))._('num', 'eq'))))); +export const eq = g('eq', _l(l => _l(r => l._(r._(True)._(cnst._(False)))._(r._(cnst._(False))._(ref('num', 'eq')))))); -export const ge = g('ge', l('l', l('r', r('r')._(True)._(r('l')._(cnst._(False))._('num', 'ge'))))); +export const ge = g('ge', _l(l => _l(r => r._(True)._(l._(cnst._(False))._(ref('num', 'ge')))))); -export const gt = g('gt', l('l', l('r', r('l')._(False)._(r('r')._(cnst._(True))._(lt))))); +export const gt = g('gt', _l(l => _l(r => l._(False)._(r._(cnst._(True))._(lt))))); -export const even = g('even', l('n', r('n')._(True)._('num', 'odd'))); +export const even = g('even', _l(n => n._(True)._(ref('num', 'odd')))); -export const odd = g('odd', l('n', r('n')._(False)._('num', 'even'))); +export const odd = g('odd', _l(n => n._(False)._(ref('num', 'even')))); -export const sum = g('sum', l('l', l('r', r('r')._('l')._(r('num', 'sum')._(Succ._('l')))))); +export const sum = g('sum', _l(l => _l(r => r._(l)._(ref('num', 'sum')._(Succ._(l)))))); -export const sub = g('sub', l('l', l('r', r('r')._('l')._(r('l')._(cnst._(Zero))._('num', 'sub'))))); +export const sub = g('sub', _l(l => _l(r => r._(l)._(l._(cnst._(Zero))._(ref('num', 'sub')))))); -export const mul = g('mul', l('l', l('r', r('l')._(Zero)._(l('pl', sum._('r')._(r('num', 'mul')._('pl')._('r'))))))); +export const mul = g('mul', _l(l => _l(r => l._(Zero)._(_l(pl => sum._(r)._(ref('num', 'mul')._(pl)._(r))))))); -export const div = g('div', l('l', l('r', iif._(lt._('l')._('r'))._(Zero)._(succ._(r('num', 'div')._(sub._('l')._('r'))._('r')))))); +export const div = g('div', _l(l => _l(r => iif._(lt._(l)._(r))._(Zero)._(succ._(ref('num', 'div')._(sub._(l)._(r))._(r)))))); -export const mod = g('mod', l('l', l('r', iif._(lt._('l')._('r'))._('l')._(r('num', 'mod')._(sub._('l')._('r'))._('r'))))); +export const mod = g('mod', _l(l => _l(r => iif._(lt._(l)._(r))._(l)._(ref('num', 'mod')._(sub._(l)._(r))._(r))))); export const fromNumber: (n: number) => Term = n => !n ? Zero : Succ._(_(() => fromNumber(n - 1))); -export const toNumber: (n: Term) => number = n => $(n._(_(0))._(l('p', _(({ p }) => _(1 + toNumber(p)))))); +export const toNumber: (n: Term) => number = n => $(n._(_(0))._(_l(p => _(({ p }) => _(1 + toNumber(p)))))); diff --git a/src/ord.show.ts b/src/ord.show.ts index 0b4dfa1..85b0282 100644 --- a/src/ord.show.ts +++ b/src/ord.show.ts @@ -1,6 +1,6 @@ -import { _, g, l, n, r } from './core'; +import { _, _l, g, n } from './core'; import { fromString as _s } from './string'; n('ord.show'); -export const show = g('show', l('o', r('o')._(_s('LT'))._(_s('EQ'))._(_s('GT')))); +export const show = g('show', _l(o => o._(_s('LT'))._(_s('EQ'))._(_s('GT')))); diff --git a/src/ord.ts b/src/ord.ts index cda20b3..d5aaab4 100644 --- a/src/ord.ts +++ b/src/ord.ts @@ -1,4 +1,4 @@ -import { $, Term, _, g, l, n, r } from './core'; +import { $, Term, _, _l, g, n, _r as ref } from './core'; n('ord'); @@ -8,16 +8,16 @@ export const enum NOrd { GT, }; -export const LT = g('LT', l('lt', l('_', l('_', 'lt')))); +export const LT = g('LT', _l(lt => _l(_ => _l(_ => lt)))); -export const EQ = g('EQ', l('_', l('eq', l('_', 'eq')))); +export const EQ = g('EQ', _l(_ => _l(eq => _l(_ => eq)))); -export const GT = g('GT', l('_', l('_', l('gt', 'gt')))); +export const GT = g('GT', _l(_ => _l(_ => _l(gt => gt)))); -export const eq = g('eq', l('l', l('r', r('l') - ._(r('r')._('bool', 'True')._('bool', 'False')._('bool', 'False')) - ._(r('r')._('bool', 'False')._('bool', 'True')._('bool', 'False')) - ._(r('r')._('bool', 'False')._('bool', 'False')._('bool', 'True'))))); +export const eq = g('eq', _l(l => _l(r => l + ._(r._(ref('bool', 'True'))._(ref('bool', 'False'))._(ref('bool', 'False'))) + ._(r._(ref('bool', 'False'))._(ref('bool', 'True'))._(ref('bool', 'False'))) + ._(r._(ref('bool', 'False'))._(ref('bool', 'False'))._(ref('bool', 'True')))))); export const fromNOrd: (o: NOrd) => Term = o => o === NOrd.LT ? LT : o === NOrd.EQ ? EQ : GT; diff --git a/src/pair.show.ts b/src/pair.show.ts index c51f8a4..491df6b 100644 --- a/src/pair.show.ts +++ b/src/pair.show.ts @@ -1,8 +1,8 @@ -import { _, g, l, n, r } from './core'; +import { _, _l, g, n } from './core'; import { uncurry } from './pair'; import { Nil, concat, cons } from './list'; import { fromString as _s } from './string'; n('pair.show'); -export const show = g('show', l('fshow', l('sshow', uncurry._(l('f', l('s', concat._(cons._(_s('('))._(cons._(r('fshow')._('f'))._(cons._(_s(', '))._(cons._(r('sshow')._('s'))._(cons._(_s(')'))._(Nil)))))))))))); +export const show = g('show', _l(fshow => _l(sshow => uncurry._(_l(f => _l(s => concat._(cons._(_s('('))._(cons._(fshow._(f))._(cons._(_s(', '))._(cons._(sshow._(s))._(cons._(_s(')'))._(Nil)))))))))))); diff --git a/src/pair.ts b/src/pair.ts index 0c33243..399249f 100644 --- a/src/pair.ts +++ b/src/pair.ts @@ -1,32 +1,32 @@ -import { _, g, l, n, r } from './core'; +import { _, _l, g, n } from './core'; import { GT, LT } from './ord'; import { False, True, and } from './bool'; import { fromString as _s } from './string'; n('pair'); -export const Pair = g('Pair', l('f', l('s', l('p', r('p')._('f')._('s'))))); +export const Pair = g('Pair', _l(f => _l(s => _l(p => p._(f)._(s))))); -export const fst = g('fst', l('p', r('p')._(l('f', l('_', 'f'))))); +export const fst = g('fst', _l(p => p._(_l(f => _l(_ => f))))); -export const snd = g('snd', l('p', r('p')._(l('_', l('s', 's'))))); +export const snd = g('snd', _l(p => p._(_l(_ => _l(s => s))))); -export const first = g('first', l('t', l('p', r('p')._(l('f', l('s', Pair._(r('t')._('f'))._('s'))))))); +export const first = g('first', _l(t => _l(p => p._(_l(f => _l(s => Pair._(t._(f))._(s))))))); -export const second = g('second', l('t', l('p', r('p')._(l('f', l('s', Pair._('f')._(r('t')._('s')))))))); +export const second = g('second', _l(t => _l(p => p._(_l(f => _l(s => Pair._(f)._(t._(s)))))))); -export const both = g('both', l('tf', l('ts', l('p', r('p')._(l('f', l('s', Pair._(r('tf')._('f'))._(r('ts')._('s'))))))))); +export const both = g('both', _l(tf => _l(ts => _l(p => p._(_l(f => _l(s => Pair._(tf._(f))._(ts._(s))))))))); -export const uncurry = g('uncurry', l('t', l('p', r('p')._('t')))); +export const uncurry = g('uncurry', _l(t => _l(p => p._(t)))); -export const cmp = g('cmp', l('fcmp', l('scmp', uncurry._(l('lf', l('ls', uncurry._(l('rf', l('rs', r('fcmp')._('lf')._('rf')._(LT)._(r('scmp')._('ls')._('rs'))._(GT)))))))))); +export const cmp = g('cmp', _l(fcmp => _l(scmp => uncurry._(_l(lf => _l(ls => uncurry._(_l(rf => _l(rs => fcmp._(lf)._(rf)._(LT)._(scmp._(ls)._(rs))._(GT)))))))))); -export const lt = g('lt', l('fcmp', l('scmp', uncurry._(l('lf', l('ls', uncurry._(l('rf', l('rs', r('fcmp')._('lf')._('rf')._(True)._(r('scmp')._('ls')._('rs')._(True)._(False)._(False))._(False)))))))))); +export const lt = g('lt', _l(fcmp => _l(scmp => uncurry._(_l(lf => _l(ls => uncurry._(_l(rf => _l(rs => fcmp._(lf)._(rf)._(True)._(scmp._(ls)._(rs)._(True)._(False)._(False))._(False)))))))))); -export const le = g('le', l('fcmp', l('scmp', uncurry._(l('lf', l('ls', uncurry._(l('rf', l('rs', r('fcmp')._('lf')._('rf')._(True)._(r('scmp')._('ls')._('rs')._(True)._(True)._(False))._(False)))))))))); +export const le = g('le', _l(fcmp => _l(scmp => uncurry._(_l(lf => _l(ls => uncurry._(_l(rf => _l(rs => fcmp._(lf)._(rf)._(True)._(scmp._(ls)._(rs)._(True)._(True)._(False))._(False)))))))))); -export const eq = g('eq', l('feq', l('seq', uncurry._(l('lf', l('ls', uncurry._(l('rf', l('rs', and._(r('feq')._('lf')._('rf'))._(r('seq')._('ls')._('rs'))))))))))); +export const eq = g('eq', _l(feq => _l(seq => uncurry._(_l(lf => _l(ls => uncurry._(_l(rf => _l(rs => and._(feq._(lf)._(rf))._(seq._(ls)._(rs))))))))))); -export const ge = g('ge', l('fcmp', l('scmp', uncurry._(l('lf', l('ls', uncurry._(l('rf', l('rs', r('fcmp')._('lf')._('rf')._(False)._(r('scmp')._('ls')._('rs')._(False)._(True)._(True))._(True)))))))))); +export const ge = g('ge', _l(fcmp => _l(scmp => uncurry._(_l(lf => _l(ls => uncurry._(_l(rf => _l(rs => fcmp._(lf)._(rf)._(False)._(scmp._(ls)._(rs)._(False)._(True)._(True))._(True)))))))))); -export const gt = g('gt', l('fcmp', l('scmp', uncurry._(l('lf', l('ls', uncurry._(l('rf', l('rs', r('fcmp')._('lf')._('rf')._(False)._(r('scmp')._('ls')._('rs')._(False)._(False)._(True))._(True)))))))))); +export const gt = g('gt', _l(fcmp => _l(scmp => uncurry._(_l(lf => _l(ls => uncurry._(_l(rf => _l(rs => fcmp._(lf)._(rf)._(False)._(scmp._(ls)._(rs)._(False)._(False)._(True))._(True)))))))))); diff --git a/src/string.ts b/src/string.ts index b6ef213..7fa3fb0 100644 --- a/src/string.ts +++ b/src/string.ts @@ -1,4 +1,4 @@ -import { $, Term, _, g, l, n } from './core'; +import { $, Term, _, _l, g, n } from './core'; import { fromChar as _c, cmp as cmpc, eq as eqc, fromChar, toChar } from './char'; import { Cons, Nil, append, cmp as cmpl, eq as eql, ge as gel, gt as gtl, le as lel, lt as ltl, nul } from './list'; @@ -22,8 +22,8 @@ export const ge = g('ge', gel._(cmpc)); export const gt = g('gt', gtl._(cmpc)); -export const wrap = g('wrap', l('w', l('c', append._('w')._(append._('c')._('w'))))); +export const wrap = g('wrap', _l(w => _l(c => append._(w)._(append._(c)._(w))))); export const fromString: (xs: string) => Term = s => !s.length ? Nil : Cons._(fromChar(s[0]))._(_(() => fromString(s.slice(1)))); -export const toString: (xs: Term) => string = s => $(s._(_(''))._(l('x', l('xs', _(({ x, xs }) => _(toChar(x) + toString(xs))))))); +export const toString: (xs: Term) => string = s => $(s._(_(''))._(_l(x => _l(xs => _(({ x, xs }) => _(toChar(x) + toString(xs))))))); diff --git a/test/list.spec.ts b/test/list.spec.ts index 913f3a0..8c1a7f1 100644 --- a/test/list.spec.ts +++ b/test/list.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from '@jest/globals'; -import { $, Term, _, g, l, n, undef } from '../src/core'; +import { $, Term, _, _l, g, n, undef, _r as ref } from '../src/core'; import { toNOrd as $o, NOrd } from '../src/ord'; import { toBoolean as $b, iif } from '../src/bool'; import { toNumber as $n, Succ, Zero, fromNumber as _n, fromNumber as _nn, cmp as cmpn, eq as eqn, even, gt as ngt, odd, succ, sum } from '../src/num'; @@ -16,7 +16,7 @@ describe('List', () => { const _na: (xs: number[]) => Term = xs => !xs.length ? Nil : Cons._(_n(xs[0]))._(_(() => _na(xs.slice(1)))); - const $na: (xs: Term) => number[] = xs => $(xs._(_([]))._(l('x', l('xs', _(({ x, xs }) => _([$n(x), ...$na(xs)])))))); + const $na: (xs: Term) => number[] = xs => $(xs._(_([]))._(_l(x => _l(xs => _(({ x, xs }) => _([$n(x), ...$na(xs)])))))); describe('toArray', () => { it('converts []', () => { @@ -60,7 +60,7 @@ describe('List', () => { }); it('handles infinite lists', () => { - expect($n(cons._(_n(0))._(infinite)._(undef)._(l('x', l('_', 'x'))))).toBe(0); + expect($n(cons._(_n(0))._(infinite)._(undef)._(_l(x => _l(_ => x))))).toBe(0); }); }); @@ -78,7 +78,7 @@ describe('List', () => { }); it('handles infinite lists', () => { - expect($n(snoc._(infinite)._(_n(0))._(undef)._(l('x', l('_', 'x'))))).toBe(0); + expect($n(snoc._(infinite)._(_n(0))._(undef)._(_l(x => _l(_ => x))))).toBe(0); }); }); @@ -142,7 +142,7 @@ describe('List', () => { }); it('handles infinite lists', () => { - expect($n(append._(infinite)._(infinite)._(undef)._(l('x', l('_', 'x'))))).toBe(0); + expect($n(append._(infinite)._(infinite)._(undef)._(_l(x => _l(_ => x))))).toBe(0); }); }); @@ -160,8 +160,8 @@ describe('List', () => { }); it('handles infinite lists', () => { - const dinfinite: Term = g('dinfinite', cons._(infinite)._('dinfinite')); - expect($n(concat._(dinfinite)._(undef)._(l('x', l('_', 'x'))))).toBe(0); + const dinfinite: Term = g('dinfinite', cons._(infinite)._(ref('list.spec', 'dinfinite'))); + expect($n(concat._(dinfinite)._(undef)._(_l(x => _l(_ => x))))).toBe(0); }); }); @@ -263,7 +263,7 @@ describe('List', () => { it('handles infinite lists', () => { expect($n( foldr - ._(l('x', l('a', sum._('x')._(iif._(eqn._(_n(5))._('x'))._(Zero)._('a'))))) + ._(_l(x => _l(a => sum._(x)._(iif._(eqn._(_n(5))._(x))._(Zero)._(a))))) ._(Zero) ._(infinite))) .toBe(15); @@ -286,7 +286,7 @@ describe('List', () => { it.failing('handles infinite lists', () => { expect($n( foldrz - ._(l('x', l('a', sum._('x')._(iif._(eqn._(_n(5))._('x'))._(Zero)._('a'))))) + ._(_l(x => _l(a => sum._(x)._(iif._(eqn._(_n(5))._(x))._(Zero)._(a))))) ._(infinite))) .toBe(15); }); diff --git a/test/num.spec.ts b/test/num.spec.ts index 0b61a72..9fd2d13 100644 --- a/test/num.spec.ts +++ b/test/num.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from '@jest/globals'; -import { Term, _, g, n, undef } from '../src/core'; +import { Term, _, g, n, _r, undef } from '../src/core'; import { toNOrd as $o, NOrd } from '../src/ord'; import { toBoolean as $b, fromBoolean as _b } from '../src/bool'; import { toNumber as $n, Succ, Zero, fromNumber as _n, cmp, div, eq, ge, gt, ifz, le, lt, mod, mul, pred, sub, succ, sum } from '../src/num'; @@ -9,7 +9,7 @@ import { show } from '../src/num.show'; n('num.spec'); describe('Num', () => { - const infinity: Term = g('infinity', _(() => Succ._('num.spec', 'infinity'))); + const infinity: Term = g('infinity', _(() => Succ._(_r('num.spec', 'infinity')))); describe('toNumber', () => { it('converts 0', () => { diff --git a/test/string.spec.ts b/test/string.spec.ts index c0c7b4b..74dceb3 100644 --- a/test/string.spec.ts +++ b/test/string.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from '@jest/globals'; -import { Term, _, g, l, n, undef } from '../src/core'; +import { Term, _, _l, g, n, undef, _r as ref } from '../src/core'; import { NOrd, toNOrd } from '../src/ord'; import { toBoolean as $b } from '../src/bool'; import { toNumber as $n, Zero, gt as ngt } from '../src/num'; @@ -10,7 +10,7 @@ import { show } from '../src/string.show'; n('string.spec'); describe('String', () => { - const infinite: Term = g('infinite', Cons._(_c('a'))._('string.spec', 'infinite')); + const infinite: Term = g('infinite', Cons._(_c('a'))._(ref('string.spec', 'infinite'))); describe('toString', () => { it('converts ""', () => { @@ -108,7 +108,7 @@ describe('String', () => { }); it('handles infinite strings', () => { - expect($c(append._(infinite)._(infinite)._(undef)._(l('x', l('_', 'x'))))).toBe('a'); + expect($c(append._(infinite)._(infinite)._(undef)._(_l(x => _l(_ => x))))).toBe('a'); }); }); @@ -122,7 +122,7 @@ describe('String', () => { }); it('handles infinite strings', () => { - expect($c(wrap._(infinite)._(infinite)._(undef)._(l('x', l('_', 'x'))))).toBe('a'); + expect($c(wrap._(infinite)._(infinite)._(undef)._(_l(x => _l(_ => x))))).toBe('a'); }); });