Skip to content

Instantly share code, notes, and snippets.

@gigamonkey
Last active November 4, 2022 15:35
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 gigamonkey/af900343d0f16d729f1e55a905ccde43 to your computer and use it in GitHub Desktop.
Save gigamonkey/af900343d0f16d729f1e55a905ccde43 to your computer and use it in GitHub Desktop.
Demonstration of Church numerals and booleans in Javascript
// Church numerals -- functions of two arguments, a function and a zero value.
// The nth Church numeral applies an n-fold compostion f to the zero value.
const Zero = (f, z) => z;
const One = (f, z) => f(z);
const Two = (f, z) => f(f(z));
const Three = (f, z) => f(f(f(z)));
// etc.
/*
Alternatively we can define a Successor function that takes a Church numeral,
n, and produces the next Church numeral and then we can build all the numerals
starting from Zero.
const Successor = (n) => (f, z) => f(n(f, z));
const One = Successor(Zero);
const Two = Successor(One);
const Three = Successor(Two);
// etc.
*/
// Numeric functions. The argument m and n are Church numerals as defined above,
// i.e. functions.
const Add = (m, n) => (f, z) => m(f, n(f, z));
const Multiply = (m, n) => (f, z) => m((x) => n(f, x), z);
// Church booleans
const True = (a, b) => a;
const False = (a, b) => b;
// Some predicates on numbers. N.B. no if's anywhere.
const IsZero = (n) => n((_) => False, True);
const IsEven = (n) => n((b) => b(False, True), True);
// The i/o layer -- to interact with the Church values we need to invoke the
// Church value functions with arguments that let us cross the bridge between
// Javascript and the Church "machine". But the specific values could be
// anything that suits our needs. (To get all abstract mathematical, the zero
// value and the function probably need to form a monoid.)
const evalNumber = (n) => n((x) => x + 1, 0);
const evalBoolean = (b) => b('TRUE', 'FALSE');
console.log(`
Do some math:
Zero: ${evalNumber(Zero)}
One: ${evalNumber(One)}
Two: ${evalNumber(Two)}
Three: ${evalNumber(Three)}
One + Two + Three: ${evalNumber(Add(Add(One, Two), Three))}
Two * Three: ${evalNumber(Multiply(Two, Three))}
(One + Two) * (Two + Three): ${evalNumber(Multiply(Add(One, Two), Add(Two, Three)))}
Booleans:
Zero is zero: ${evalBoolean(IsZero(Zero))}
One is zero: ${evalBoolean(IsZero(One))}
Zero is even: ${evalBoolean(IsEven(Zero))}
One is even: ${evalBoolean(IsEven(One))}
Two is even: ${evalBoolean(IsEven(Two))}
Three is even: ${evalBoolean(IsEven(Three))}
Two + Three is even: ${evalBoolean(IsEven(Add(Two, Three)))}
`);
@gigamonkey
Copy link
Author

Do some math:
Zero: 0
One: 1
Two: 2
Three: 3
One + Two + Three: 6
Two * Three: 6
(One + Two) * (Two + Three): 15

Booleans:
Zero is zero: TRUE
One is zero: FALSE
Zero is even: TRUE
One is even: FALSE
Two is even: TRUE
Three is even: FALSE
Two + Three is even: FALSE

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