Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Przemyslaw Jan Pietrzak remove dead link from Reader docs a535f55 Jun 18, 2018
2 contributors

Users who have contributed to this file

@ulfryk @tomecko
102 lines (66 sloc) 2.53 KB

Reader

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

Methods

map

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

Maps the supplied function over the Reader.

flatMap

Aliases: bind, chain

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

Performs a monadic bind over the Reader.

ap

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.

run

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

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

...and undocumented

  • join
  • takeLeft
  • takeRight
  • local
You can’t perform that action at this time.