Skip to content

Instantly share code, notes, and snippets.

@tdreyno
Created April 22, 2020 01:34
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 tdreyno/e7731738ceb9ef92557d88a87b626c7f to your computer and use it in GitHub Desktop.
Save tdreyno/e7731738ceb9ef92557d88a87b626c7f to your computer and use it in GitHub Desktop.
Basic church encoding in JS
// 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'))
@tdreyno
Copy link
Author

tdreyno commented Apr 22, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment