0

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?

  • If you define an Applicative instance for your Reader type (which you haven't really defined anywhere, not even as an alias), where is `pure`? – Bergi Jun 06 '20 at 12:50
  • Please try deriving the types for all of your functions and annotating them. This should make the code more understandable for us, and highlight any potential mistakes. – Bergi Jun 06 '20 at 12:52

0 Answers0