Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time


The Reader monad is a wonderful solution to inject dependencies into your functions.

The Reader monad provides a way to "weave" your configuration throughout your programme.

Creating a Reader

Say you had this function which requires configuration:

const createPrettyName = (name, printer) => printer.write("hello " + name)

Calling this function from other functions that don't need the dependency printer is kind of awkward.

const render = printer => createPrettyName("Tom", printer)

One quick win would be to curry the createPrettyName function, and make render partially apply the function and let the caller of render supply the printer.

const createPrettyName = name => printer => printer.write("hello " + name)

const render = () => createPrettyName("Tom")

This is better, but what if render wants to perform some sort of operation on the result of createPrettyName? It would have to apply the final parameter (i.e. the printer) before createPrettyName would execute.

This where the Reader monad comes in. We could rewrite createPrettyName thusly:

const createPrettyName = name =>
  Reader(printer => printer.write("hello " + name))

To sweeten up the syntax a little we can also write (using monet-pimp module):

const createPrettyName = ((name, printer) => printer.write("hello " + name)).reader()

So now, when a name is supplied to createPrettyName the Reader monad is returned and being a monad it supports all the monadic goodness.

We can now get access to the result of createPrettyName through a map.

const reader = () =>
  createPrettyName("Tom").map(s => `---${s}---`)

The top level of our programme would co-ordinate the injecting of the dependency by calling run on the resulting Reader.

reader().run(new BoldPrinter())



Reader[E, A].map(f: A => B): Reader[E, B]

Maps the supplied function over the Reader.


Aliases: bind, chain

Reader[E, A].bind(fn: A => Reader[E, B]): Reader[E, B]

Performs a monadic bind over the Reader.


Reader[E, A].ap(a: Reader[E, A=>B]): Reader[E, B]

Applies the function inside the supplied Reader to the value A in the outer Reader. Applicative Functor pattern.


Reader[E, A=>B].apTo(a: Reader[E, A]): Reader[E, B]

Just an alias for ap with swapped this & argument.


Reader[E, A].run(env: E): A;

Executes the function wrapped in the Reader with the supplied config.

...and undocumented

  • join
  • takeLeft
  • takeRight
  • local