import { toNative as $$, L, P, _, fromNative as __, ___, cnst, id, undef } from './core'; import { EQ, GT, LT, Ord, eq as eqc } from './ord'; import { Bool, False, True, and, iif, or } from './bool'; import { Num, Zero, succ } from './num'; import { String, fromString as _s } from './string'; export type List = L<(z: R) => L<(f: L<(x: T) => L<(xs: List) => R>>) => R>>; export const Nil: List = _(z => _(_f => z)) as List; export const Cons: L<(x: T) => L<(xs: List) => List>> = _((x: T) => _((xs: List) => _(_z => _(f => f(x)(xs))) as List)); export const cons: L<(x: T) => L<(xs: List) => List>> = Cons; export const snoc: L<(xs: List) => L<(x: T) => List>> = _((xs: List) => _((x: T) => xs(cons(x)(Nil))(_(y => _(ys => cons(y)(snoc(ys)(x))))))); export const nul: L<(xs: List) => Bool> = _(xs => xs(True)(cnst(cnst(False)))); export const len: L<(xs: List) => Num> = _(xs => xs(Zero)(_(_x => _(xs => succ(len(xs)))))); export const append: L<(l: List) => L<(r: List) => List>> = _(l => _(r => l(r)(_(x => _(xs => cons(x)(append(xs)(r))))))); export const concat: L<(ls: List>) => List> = _(ls => ls(Nil)(_(x => _(xs => append(x)(concat(xs)))))); export const repeat: L<(x: T) => List> = _(x => cons(x)(repeat(x))); export const iterate: L<(f: L<(x: T) => T>) => L<(x: T) => List>> = _((f: L<(x: T) => T>) => _((x: T) => cons(x)(iterate(f)(f(x))))); export const head: L<(xs: List) => T> = _(xs => xs(undef)(cnst)); export const tail: L<(xs: List) => List> = _(xs => xs(undef)(cnst(id))); export const foldl: L<(f: L<(a: R) => L<(x: T) => R>>) => L<(z: R) => L<(xs: List) => R>>> = _((f: L<(a: R) => L<(x: T) => R>>) => _((z: R) => _((xs: List) => xs(z)(_(x => foldl(f)(f(z)(x))))))); export const foldlz: L<(f: L<(a: T) => L<(x: T) => T>>) => L<(xs: List) => T>> = _((f: L<(a: T) => L<(x: T) => T>>) => _((xs: List) => xs(undef)(foldl(f)))); export const foldr: L<(f: L<(x: T) => L<(a: R) => R>>) => L<(z: R) => L<(xs: List) => R>>> = _((f: L<(x: T) => L<(a: R) => R>>) => _((z: R) => _((xs: List) => xs(z)(_(x => _(xs => f(x)(foldr(f)(z)(xs)))))))); export const foldrz: L<(f: L<(x: T) => L<(a: T) => T>>) => L<(xs: List) => T>> = undef; export const cmp: L<(ecmp: L<(l: T) => L <(r: T) => Ord>>) => L<(l: List) => L<(r: List) => Ord>>> = _((ecmp: L<(l: T) => L<(r: T) => Ord>>) => _((l: List) => _((r: List) => l (r(EQ)(cnst(cnst(LT)))) (_(lx => _(lxs => r(GT)(_(rx => _(rxs => iif (eqc(EQ)(ecmp(lx)(rx))) (cmp(ecmp)(lxs)(rxs)) (ecmp(lx)(rx))))))))))); export const lt: L<(ecmp: L<(l: T) => L <(r: T) => Ord>>) => L<(l: List) => L<(r: List) => Bool>>> = _((ecmp: L<(l: T) => L<(r: T) => Ord>>) => _((l: List) => _((r: List) => r(False)(_(rx => _(rxs => l(True)(_(lx => _(lxs => ecmp(lx)(rx)(True)(lt(ecmp)(lxs)(rxs))(False)))))))))); export const le: L<(ecmp: L<(l: T) => L <(r: T) => Ord>>) => L<(l: List) => L<(r: List) => Bool>>> = _((ecmp: L<(l: T) => L<(r: T) => Ord>>) => _((l: List) => _((r: List) => l(True)(_(lx => _(lxs => r(False)(_(rx => _(rxs => ecmp(lx)(rx)(True)(le(ecmp)(lxs)(rxs))(False)))))))))); export const eq: L<(eeq: L<(l: T) => L <(r: T) => Bool>>) => L<(l: List) => L<(r: List) => Bool>>> = _((eeq: L<(l: T) => L<(r: T) => Bool>>) => _((l: List) => _((r: List) => l (r(True)(cnst(cnst(False)))) (_(lx => _(lxs => r(False)(_(rx => _(rxs => and(eeq(lx)(rx))(eq(eeq)(lxs)(rxs))))))))))); export const ge: L<(ecmp: L<(l: T) => L <(r: T) => Ord>>) => L<(l: List) => L<(r: List) => Bool>>> = _((ecmp: L<(l: T) => L<(r: T) => Ord>>) => _((l: List) => _((r: List) => r(True)(_(rx => _(rxs => l(False)(_(lx => _(lxs => ecmp(lx)(rx)(False)(ge(ecmp)(lxs)(rxs))(True)))))))))); export const gt: L<(ecmp: L<(l: T) => L <(r: T) => Ord>>) => L<(l: List) => L<(r: List) => Bool>>> = _((ecmp: L<(l: T) => L<(r: T) => Ord>>) => _((l: List) => _((r: List) => l(False)(_(lx => _(lxs => r(True)(_(rx => _(rxs => ecmp(lx)(rx)(False)(gt(ecmp)(lxs)(rxs))(True)))))))))); export const map: L<(f: L<(x: T) => R>) => L<(xs: List) => List>> = _((f: L<(x: T) => R>) => _((xs: List) => xs(Nil)(_(x => _(xs => cons(f(x))(map(f)(xs))))))); export const filter: L<(f: L<(x: T) => Bool>) => L<(xs: List) => List>> = _((f: L<(x: T) => Bool>) => _((xs: List) => xs(Nil)(_(x => _(xs => iif(f(x))(cons(x))(id)(filter(f)(xs))))))); export const any: L<(f: L<(x: T) => Bool>) => L<(xs: List) => Bool>> = _((f: L<(x: T) => Bool>) => _((xs: List) => xs(False)(_(x => _(xs => or(f(x))(any(f)(xs))))))); export const all: L<(f: L<(x: T) => Bool>) => L<(xs: List) => Bool>> = _((f: L<(x: T) => Bool>) => _((xs: List) => xs(True)(_(x => _(xs => and(f(x))(all(f)(xs))))))); export const get: L<(i: Num) => L<(xs: List) => T>> = _(i => _(xs => xs(undef)(_(x => i(cnst(x))(get))))); export const update: L<(f: L< (p: T) => T>) => L<(i: Num) => L<(xs: List) => List>>> = _((f: L< (p: T) => T>) => _((i: Num) => _((xs: List) => xs(undef)(_(x => _(xs => i(cons(f(x))(xs))(_(pi => cons(x)(update(f)(pi)(xs)))))))))); export const set: L<(v: T) => L<(i: Num) => L<(xs: List) => List>>> = _(v => update(cnst(v))); export const intersperse: L<(v: T) => L<(xs: List) => List>> = _(v => _(xs => xs(xs)(_(x => _(rxs => rxs(xs)(cnst(cnst(cons(x)(cons(v)(intersperse(v)(rxs))))))))))); export const show: L<(eshow: L<(e: T) => String>) => L<(xs: List) => String>> = _(eshow => _(xs => concat(snoc(cons(_s('['))(intersperse(_s(', '))(map(eshow)(xs))))(_s(']'))))); export const fromArray: (xs: T[]) => List = xs => xs.length === 0 ? Nil : cons(xs[0])(___(() => fromArray(xs.slice(1)).run())); export const toArray: (xs: List) => P[] = xs => $$(xs(__([]))(_(x => _(xs => __([x, ...toArray(xs)])))));