Created
April 22, 2020 01:34
-
-
Save tdreyno/e7731738ceb9ef92557d88a87b626c7f to your computer and use it in GitHub Desktop.
Basic church encoding in JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Lambda calculus: Church 1940-ish | |
// | |
// <expression> := <name> | <function> | <application> | |
// <function> := λ <name>.<expression> | |
// <application> := <expression><expression> | |
// | |
// expression := name | function | application | |
// function := name => expression | |
// application := expression(expression) | |
// | |
// lambdas are unary | |
// lambdas have equality: (a => b) === (c => d) | |
const zero = s => z => z | |
const one = s => z => s(z) | |
const two = s => z => s(s(z)) | |
const three = s => z => s(s(s(z))) | |
// Add 1 to a number | |
const SUCCESSOR = a => b => c => b(a(b)(c)) | |
const four = SUCCESSOR(three) | |
// Add X to a number | |
const ADD = a => b => a(SUCCESSOR)(b) | |
const five = ADD(one)(four) | |
// Multiply numbers | |
const MULT = a => b => c => a(b(c)) | |
const six = MULT(two)(three) | |
// True and False | |
const T = x => y => x | |
const F = x => y => y | |
// Negate a boolean | |
const NOT = a => a(F)(T) | |
// And/Or logic | |
const AND = a => b => a(b)(F) | |
const OR = a => b => a(T)(b) | |
// Equality | |
const IS_ZERO = a => a(F)(NOT)(F) | |
const GREATER_OR_EQUAL = n => m => IS_ZERO(n(PREDECESSOR)(m)) | |
const EQUAL = n => m => AND(GREATER_OR_EQUAL(n)(m))(GREATER_OR_EQUAL(m)(n)) | |
// Subtract 1 from a number | |
const PREDECESSOR = n => f => x => n(g => h => h(g(f)))(u => x)(u => u) | |
const seven = PREDECESSOR(MULT(two)(four)) | |
// Substract X from a number | |
const SUB = a => b => b(PREDECESSOR)(a) | |
const subThree = SUB(four)(one) | |
// LOG | |
const toStr = n => n(a => `s(${a})`)('z') | |
console.log('3', toStr(three)) | |
console.log('4', toStr(four)) | |
console.log('6', toStr(six)) | |
console.log('7', toStr(seven)) | |
console.log('sub3', toStr(subThree)) | |
console.log('isZero(0)', IS_ZERO(zero)) | |
console.log('isZero(1)', IS_ZERO(one)) | |
console.log('NOT(T)', NOT(T)) | |
console.log('NOT(F)', NOT(F)) | |
console.log('AND(T)(T)', AND(T)(T)) | |
console.log('AND(T)(F)', AND(T)(F)) | |
console.log('AND(F)(F)', AND(F)(F)) | |
console.log('OR(T)(T)', OR(T)(T)) | |
console.log('OR(T)(F)', OR(T)(F)) | |
console.log('OR(F)(F)', OR(F)(F)) | |
console.log('gte(1, 3)', GREATER_OR_EQUAL(one)(three)) | |
console.log('gte(4, 2)', GREATER_OR_EQUAL(four)(two)) | |
console.log('gte(3, 3)', GREATER_OR_EQUAL(three)(three)) | |
console.log('EQUAL(6, 6)', EQUAL(six)(ADD(four)(two))) | |
console.log('EQUAL(6, 8)', EQUAL(six)(MULT(four)(two))) | |
const foldBool = tf => t => f => tf(t)(f)() | |
foldBool(AND(T)(T))(() => console.log('and is true'))(() => console.log('and is false')) | |
foldBool(EQUAL(six)(MULT(four)(two)))(() => console.log('equal is true'))(() => console.log('equal is false')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://en.wikipedia.org/wiki/Church_encoding