Skip to content

Instantly share code, notes, and snippets.

@eiriklv
Forked from arian/church.js
Created September 20, 2016 22:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eiriklv/9589eca2c7a021cba699a274cf0d385a to your computer and use it in GitHub Desktop.
Save eiriklv/9589eca2c7a021cba699a274cf0d385a to your computer and use it in GitHub Desktop.
Church Numerals, Booleans, Pairs and Lists in JavaScript (ES6)
// conversions
let c2i = x => x(y => y + 1, 0)
let c2star = x => x(y => y + '*', '')
let c2b = x => x('True', 'False')
let c2a = xs => xs((y, ys) => [c2i(y)].concat(ys), [])
// numbers
let zero = (s,z) => z
let one = (s,z) => s(z)
let two = (s,z) => s(s(z))
let three = (s,z) => s(s(s(z)))
// booleans
let t = (a,b) => a
let f = (a,b) => b
// boolean operators
let and = (x,y) => (a,b) => x(y(a, b), b)
let or = (x,y) => (a,b) => x(a, y(a, b))
let not = x => (a,b) => x(b, a)
// pair
let pair = (a,b) => s => s(a, b)
let fst = x => x((a, b) => a)
let snd = x => x((a, b) => b)
// number operations
// successor
let succ = x => (s,z) => s(x(s, z))
// adding
let add = (x,y) => x(p => succ(p, one), y)
// multiplying
let mul = (x,y) => x(p => add(p, y), zero)
// exponent
let exp = (x,y) => y(p => mul(p, x), one)
// decrease
let dec = n => fst(n(b => pair(snd(b), succ(snd(b))), pair(zero, zero)))
// subtract
let sub = (x,y) => y(p => dec(p), x)
// zero test
let iszero = x => x(_ => f, t)
// compare
let lt = (x, y) => and(iszero(sub(x, y)), not(iszero(sub(y, x))))
let leq = (x,y) => iszero(sub(x, y))
let eq = (x,y) => and(iszero(sub(x, y)), iszero(sub(y, x)))
let geq = (x,y) => not(lt(x,y))
let gt = (x,y) => not(leq(x,y))
// lists
let nil = (s, z) => z
let isnil = xs => xs(_ => f, t)
let cons = (x, xs) => (s,z) => s(x, xs(s, z))
let head = xs => (s, z) => xs((y, ys) => y(s, z))
let tail = xs => fst(xs((y, ys) => pair(snd(ys), cons(y, snd(ys))), pair(nil, nil)))
// logging
let logi = x => console.log(x.toString().slice(24, -3), c2i(x()))
let logb = x => console.log(x.toString().slice(24, -3), c2b(x()))
let loga = x => console.log(x.toString().slice(24, -3), c2a(x()))
logi(_ => zero)
logi(_ => one)
logi(_ => two)
logi(_ => add(one, succ(two)))
logi(_ => mul(two, three))
logi(_ => exp(three, two))
logi(_ => dec(two))
logi(_ => sub(exp(two, three), two))
logb(_ => not(t))
logb(_ => not(f))
logb(_ => and(t, t))
logb(_ => and(f, t))
logb(_ => and(t, f))
logb(_ => and(f, f))
logb(_ => or(t, t))
logb(_ => or(f, t))
logb(_ => or(t, f))
logb(_ => or(f, f))
logb(_ => iszero(zero))
logb(_ => iszero(one))
logb(_ => iszero(two))
logb(_ => eq(one, two))
logb(_ => eq(two, two))
logb(_ => eq(two, one))
logb(_ => leq(one, two))
logb(_ => leq(two, two))
logb(_ => leq(two, one))
logb(_ => lt(one, two))
logb(_ => lt(two, two))
logb(_ => lt(two, one))
logb(_ => geq(one, two))
logb(_ => geq(two, two))
logb(_ => geq(two, one))
logb(_ => gt(one, two))
logb(_ => gt(two, two))
logb(_ => gt(two, one))
loga(_ => nil)
loga(_ => cons(one, nil))
loga(_ => cons(two, cons(one, nil)))
logb(_ => isnil(nil))
logb(_ => isnil(cons(one, nil)))
logi(_ => head(cons(two, nil)))
loga(_ => tail(cons(zero, cons(one, cons(two, nil)))))
console.log(c2star(add(two, succ(two))))
"_zero"
0
"_one"
1
"_two"
2
"_add(_one, _succ(_two))"
4
"_mul(_two, _three)"
6
"_exp(_three, _two)"
9
"_dec(_two)"
1
"_sub(_exp(_two, _three), _two)"
6
"_not(_t)"
"False"
"_not(_f)"
"True"
"_and(_t, _t)"
"True"
"_and(_f, _t)"
"False"
"_and(_t, _f)"
"False"
"_and(_f, _f)"
"False"
"_or(_t, _t)"
"True"
"_or(_f, _t)"
"True"
"_or(_t, _f)"
"True"
"_or(_f, _f)"
"False"
"_iszero(_zero)"
"True"
"_iszero(_one)"
"False"
"_iszero(_two)"
"False"
"_eq(_one, _two)"
"False"
"_eq(_two, _two)"
"True"
"_eq(_two, _one)"
"False"
"_leq(_one, _two)"
"True"
"_leq(_two, _two)"
"True"
"_leq(_two, _one)"
"False"
"_lt(_one, _two)"
"True"
"_lt(_two, _two)"
"False"
"_lt(_two, _one)"
"False"
"_geq(_one, _two)"
"False"
"_geq(_two, _two)"
"True"
"_geq(_two, _one)"
"True"
"_gt(_one, _two)"
"False"
"_gt(_two, _two)"
"False"
"_gt(_two, _one)"
"True"
"_nil"
[]
"_cons(_one, _nil)"
[1]
"_cons(_two, _cons(_one, _nil))"
[2, 1]
"_isnil(_nil)"
"True"
"_isnil(_cons(_one, _nil))"
"False"
"_head(_cons(_two, _nil))"
2
"_tail(_cons(_zero, _cons(_one, _cons(_two, _nil))))"
[1, 2]
"*****"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment