109 lines
2.1 KiB
JavaScript
109 lines
2.1 KiB
JavaScript
(() => {
|
|
'use strict';
|
|
|
|
// ----------------- CHURCH NUMERALS -----------------
|
|
|
|
const churchZero = f =>
|
|
identity;
|
|
|
|
|
|
const churchSucc = n =>
|
|
f => compose(f)(n(f));
|
|
|
|
|
|
const churchAdd = m =>
|
|
n => f => compose(n(f))(m(f));
|
|
|
|
|
|
const churchMult = m =>
|
|
n => f => n(m(f));
|
|
|
|
|
|
const churchExp = m =>
|
|
n => n(m);
|
|
|
|
|
|
const intFromChurch = n =>
|
|
n(succ)(0);
|
|
|
|
|
|
const churchFromInt = n =>
|
|
compose(
|
|
foldl(compose)(identity)
|
|
)(
|
|
replicate(n)
|
|
);
|
|
|
|
|
|
// Or, by explicit recursion:
|
|
const churchFromInt_ = x => {
|
|
const go = i =>
|
|
0 === i ? (
|
|
churchZero
|
|
) : churchSucc(go(pred(i)));
|
|
return go(x);
|
|
};
|
|
|
|
|
|
// ---------------------- TEST -----------------------
|
|
// main :: IO ()
|
|
const main = () => {
|
|
const [cThree, cFour] = map(churchFromInt)([3, 4]);
|
|
|
|
return map(intFromChurch)([
|
|
churchAdd(cThree)(cFour),
|
|
churchMult(cThree)(cFour),
|
|
churchExp(cFour)(cThree),
|
|
churchExp(cThree)(cFour),
|
|
]);
|
|
};
|
|
|
|
|
|
// --------------------- GENERIC ---------------------
|
|
|
|
// compose (>>>) :: (a -> b) -> (b -> c) -> a -> c
|
|
const compose = f =>
|
|
g => x => f(g(x));
|
|
|
|
|
|
// foldl :: (a -> b -> a) -> a -> [b] -> a
|
|
const foldl = f =>
|
|
a => xs => [...xs].reduce(
|
|
(x, y) => f(x)(y),
|
|
a
|
|
);
|
|
|
|
|
|
// identity :: a -> a
|
|
const identity = x => x;
|
|
|
|
|
|
// map :: (a -> b) -> [a] -> [b]
|
|
const map = f =>
|
|
// The list obtained by applying f
|
|
// to each element of xs.
|
|
// (The image of xs under f).
|
|
xs => [...xs].map(f);
|
|
|
|
|
|
// pred :: Enum a => a -> a
|
|
const pred = x =>
|
|
x - 1;
|
|
|
|
|
|
// replicate :: Int -> a -> [a]
|
|
const replicate = n =>
|
|
// n instances of x.
|
|
x => Array.from({
|
|
length: n
|
|
}, () => x);
|
|
|
|
|
|
// succ :: Enum a => a -> a
|
|
const succ = x =>
|
|
1 + x;
|
|
|
|
// MAIN ---
|
|
console.log(JSON.stringify(main()));
|
|
})();
|