RosettaCodeData/Task/Church-numerals/JavaScript/church-numerals.js

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()));
})();