The Reader
monad covers computations that share a common environment. The only meaningful way to do this with functions is to implicitly thread arguments through a composition. So I attempted to create a most minimal example that still reflects the notion of such a computation.
Please note that I only use the applicative part of monad, because the computation neither depends on a previous value nor needs short circuiting. Besides I know that Reader
is almost always used as part of a transformer stack, but I want to keep this example as simple as possible:
// Applicative
const funAp = tf => tg => x =>
tf(x) (tg(x));
const id = x => x;
const ask = id;
// functions with a common parameter
const myInc = env => x => {
const r = x + 1;
if (env.debug)
console.log(r);
return r;
};
const mySqr = env => x => {
const r = x * x;
if (env.debug)
console.log(r);
return r;
};
const myAdd = env => x => y => {
const r = x + y;
if (env.debug)
console.log(r);
return r;
}
// inside sharedEnv we can use f and g without explicitly passing env
// if a fun (env.op) isn't lifted yet we ask for env
const sharedEnv = env => f => g => x =>
env.defaultOp
? f(g(x))
: funAp(env.op) (ask) (f(x)) (g(x));
// MAIN
const main = funAp(
funAp(sharedEnv)
(myInc))
(mySqr)
({debug: true, defaultOp: false, op: myAdd});
console.log(
main(5));
Does this example conform with the notion of a shared environment?