Last active
April 18, 2022 11:26
-
-
Save abiodun0/7f9c3ce22e06e23381e5918f4b000860 to your computer and use it in GitHub Desktop.
Church Encoding / Peano Numbers
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
const zero = () => false; | |
const isZero = (a) => a == zero(); | |
const succ = (a) => () => a; | |
const pred = (a) => a(); | |
const converToPeano = (n, acc = zero()) => n === 0 ? acc : converToPeano(n - 1, succ(acc)) | |
const _0 = zero(), | |
_1 = succ(_0), | |
_2 = succ(_1), | |
_3 = succ(_2), | |
_4 = succ(_3), | |
_5 = succ(_4); | |
const five = converToPeano(5) | |
const four = pred(five) | |
// Regular Arithmentic with just functions | |
const add = (a, b) => isZero(a) ? b : add(pred(a), succ(b)); | |
const sub = (a, b) => isZero(a) || isZero(b) ? a : sub(pred(a), pred(b)); | |
const mul = (a, b) => isZero(a) ? zero() : add(mul(pred(a), b), b); | |
const div = (a, b) => isZero(a) ? zero() : succ(div(sub(a, b), b)); | |
// Equality with just functions | |
const equal = (a, b) => isZero(a) ? isZero(b) : isZero(b) ? false : equal(pred(a), pred(b)); | |
const less = (a, b) => isZero(a) ? !isZero(b) : isZero(b) ? false : less(pred(a), pred(b)); | |
const greater = (a, b) => ! (equal(a, b) || less(a, b)); | |
// For debugging purposes | |
const toNumber = (a) => isZero(a) ? 0 : 1 + toNumber(pred(a)); | |
console.log(toNumber(five), 'are we correct?') | |
console.log(toNumber(add(_1, _2))); // 10 | |
console.log(toNumber(whatAreyou)); // 10 | |
console.log(toNumber(div(add(_2, _2), _2))); // 2 | |
console.log(equal(add(_1, _1), div(_4, _2))); // true | |
console.log(less(div(_4, _2), _4)); // true | |
console.log(greater(mul(_4, _2), _5)); // true |
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
const zero = Symbol() | |
const isZero = a => a === zero | |
const succ = a => () => a | |
const pred = a => a() | |
// convienince for converting | |
const toPeano = (n, acc=zero) => { | |
if(n === 0) { | |
return acc | |
} | |
return toPeano(n - 1, succ(acc)) | |
} | |
// convienince for debugging used below | |
const toNumber = (peano) => { | |
if (peano === zero) { | |
return 0; | |
} | |
return 1 + toNumber(pred(peano)) | |
} | |
const _0 = zero, | |
_1 = succ(zero), | |
_2 = succ(_1), | |
_3 = succ(_2), | |
_4 = succ(_3), | |
_5 = succ(_4), | |
_6 = succ(_5), | |
_7 = succ(_6), | |
_8 = succ(_7), | |
_9 = succ(_8); | |
// Arithmentic | |
const add = (a, b) => { | |
if(a === zero) { | |
return b; | |
} | |
if (b === zero) { | |
return a; | |
} | |
return add(pred(a), succ(b)) | |
} | |
const sub = (a, b) => { | |
if (a === zero) { | |
return zero; | |
} | |
if (b === zero) { | |
return a; | |
} | |
return sub(pred(a), pred(b)) | |
} | |
const multiply = (a, b) => { | |
if(a === zero || b === zero ) { | |
return zero; | |
} | |
return add(multiply(pred(a), b), b) | |
} | |
const div = (a, b) => { | |
if (a === zero) { | |
return zero | |
} | |
return succ(div(sub(a, b), b)) | |
} | |
// Equality | |
const equal = (a, b) => { | |
if(a === zero && b === zero) { | |
return true | |
} | |
if(a === zero && b !== zero || a !== zero && b === zero) { | |
return false | |
} | |
return equal(pred(a), pred(b)) | |
} | |
const less = (a, b) => { | |
if(a === zero && b !== zero) { | |
return true | |
} | |
if(a !== zero && b === zero || a === 0 && b === 0) { | |
return false | |
} | |
return less(pred(a), pred(b)) | |
} | |
const greater = (a, b) => { | |
if(a !== zero && b === zero) { | |
return true | |
} | |
if(a === zero && b !== zero || a === 0 && b === 0) { | |
return false | |
} | |
return greater(pred(a), pred(b)) | |
} | |
// Examples | |
console.log(toNumber(add(_5, _5)), 'is it 10?') | |
console.log(toNumber(sub(_8, _5)), 'is it 3?') | |
console.log(toNumber(multiply(_8, _2)), 'is it 16?') | |
console.log(toNumber(multiply(_9, _9)), 'is it 81?') | |
console.log(toNumber(multiply(_8, _0)), 'is it 0?') | |
console.log(toNumber(div(_8, _4)), 'is it 2?') | |
console.log((equal(_8, _8)), 'is it true') | |
console.log((equal(_8, _7)), 'is it false') | |
console.log((less(_8, _7)), 'is it false') | |
console.log((less(_4, _5)), 'is it false') | |
console.log((greater(_8, _7)), 'is it true') | |
console.log((greater(_7, _9)), 'is it false') | |
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
const zero = Symbol() | |
const isZero = a => a === zero | |
const succ = a => () => a | |
const pred = a => a() | |
// convienince for converting | |
const toPeano = (n, acc=zero) => { | |
if(n === 0) { | |
return acc | |
} | |
return toPeano(n - 1, succ(acc)) | |
} | |
// convienince for debugging used below | |
const toNumber = (peano) => { | |
if (peano === zero) { | |
return 0; | |
} | |
return 1 + toNumber(pred(peano)) | |
} | |
const _0 = zero, | |
_1 = succ(zero), | |
_2 = succ(_1), | |
_3 = succ(_2), | |
_4 = succ(_3), | |
_5 = succ(_4), | |
_6 = succ(_5), | |
_7 = succ(_6), | |
_8 = succ(_7), | |
_9 = succ(_8); | |
// Arithmentic | |
const add = (a, b) => { | |
if(isZero(a)) { | |
return b; | |
} | |
if (isZero(b)) { | |
return a; | |
} | |
return add(succ(a), pred(b)) | |
} | |
const sub = (a, b) => { | |
if (isZero(a)) { | |
return zero; | |
} | |
if (isZero(b)) { | |
return a; | |
} | |
return sub(pred(a), pred(b)) | |
} | |
const multiply = (a, b) => { | |
if(isZero(a) ||isZero(b) ) { | |
return zero; | |
} | |
return add(b, multiply(pred(a), b)) | |
} | |
const div = (a, b) => { | |
if (isZero(a)) { | |
return zero | |
} | |
return succ(div(sub(a, b), b)) | |
} | |
const exp = (a, b) => { | |
if(isZero(a)) { | |
return zero | |
} | |
if(isZero(b)) { | |
return succ(zero) | |
} | |
return multiply(exp(a, pred(b)), a) | |
} | |
// for a sample | |
// exp(4, 3) | |
// multiply(exp(4, 2), 4) | |
// multiply(multiply(exp(4, 1), 4), 4) | |
// multiply(multiply(multiply(exp(4, 0), 4), 4), 4) | |
// multiply(multiply(multiply(1, 4), 4), 4) | |
const log = (a, b) => { | |
if(isZero(b())) { | |
return zero | |
} | |
return succ(log(a, div(b, a))) | |
} | |
// Equality | |
const equal = (a, b) => { | |
if(isZero(a) && isZero(b)) { | |
return true | |
} | |
if(isZero(a) && !(isZero(b)) || !isZero(a) && isZero(b)) { | |
return false | |
} | |
return equal(pred(a), pred(b)) | |
} | |
const less = (a, b) => { | |
if(isZero(a) && !isZero(b)) { | |
return true | |
} | |
if(!isZero(a) && isZero(b) || isZero(a) && isZero(b)) { | |
return false | |
} | |
return less(pred(a), pred(b)) | |
} | |
const greater = (a, b) => { | |
if(!isZero(a) && isZero(b)) { | |
return true | |
} | |
if(isZero(a) && !isZero(b) || isZero(a) && isZero(b)) { | |
return false | |
} | |
return greater(pred(a), pred(b)) | |
} | |
// Examples | |
console.log(toNumber(add(_5, _5)), 'is it 10?') | |
console.log(toNumber(sub(_8, _5)), 'is it 3?') | |
console.log(toNumber(multiply(_8, _2)), 'is it 16?') | |
console.log(toNumber(multiply(_9, _9)), 'is it 81?') | |
console.log(toNumber(multiply(_8, _0)), 'is it 0?') | |
console.log(toNumber(multiply(_8, _0)), 'is it 0?') | |
console.log(toNumber(exp(_5, _2)), 'is it 25? exponential') | |
console.log(toNumber(exp(toPeano(10), _2)), 'is it 100? exponential') | |
console.log(toNumber(div(_8, _4)), 'is it 2?') | |
console.log((equal(_8, _8)), 'is it true') | |
console.log((equal(_8, _7)), 'is it false') | |
console.log((less(_8, _7)), 'is it false less') | |
console.log((less(_4, _5)), 'is it true less') | |
console.log((greater(_8, _7)), 'is it true') | |
console.log((greater(_7, _9)), 'is it false') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment