This post will cover the [foundations](https://hackernoon.com/tagged/foundations). It will mostly be an exercise in [learning](https://hackernoon.com/tagged/learning) how to specialize types, simplify the substitutions and come up with the only reasonable implementation. ### Motivation The `Reader` monad, or more generally the `MonadReader` interface, solves the problem of threading the same configuration to many functions. \-- Imagine this is a directory type Config = FilePath load :: Config -> String -> IO String load config x = readFile (config ++ x) loadRevision :: Config -> Int -> IO String loadRevision config x = load config ("history" ++ show x ++ ".txt") loadAll :: Config -> Int -> String -> IO (String, String) loadAll config x y = do a <- load config y b <- loadRevision config x return (a, b) If you look at `loadAll` you’ll see `config` is not used, but is threaded through to the child functions. This is a common source of boilerplate and the reader monad attempts to ameliorate it. So instead of threading the `config` to each function, we can rewrite this using `MonadReader` and the configuration will get passed implicitly. To retrieve the configuration, we call `ask`: \-- Imagine this is a directory type Config = FilePath load :: (MonadReader Config m, MonadIO m) => String -> m String load x = do config <- ask liftIO $ readFile (config ++ x) loadRevision :: (MonadReader Config m, MonadIO m) => Int -> m String loadRevision x = load ("history" ++ show x ++ ".txt") loadAll :: (MonadReader Config m, MonadIO m) => Int -> String -> m (String, String) loadAll x y = do a <- load y b <- loadRevision x return (a, b) If you look at the intermediate functions `loadRevision` and `loadAll` we no longer have to take in and pass the config around. However the “leaf” function `load` has gotten more complicated. We will later extend this example to make it reusable across concrete configurations and compare it to alternatives; but first some basics. ### ( (->) e), Reader, ReaderT and MonadReader When Haskellers mention the “reader monad” they could be referring to one of four related things: 1. The `Monad` instance for functions with the same first argument, which is written somewhat inscrutably as `((->) e)` (which I think of as `(e ->)`). 2. `type Reader = ReaderT Identity` 3. The `ReaderT` type 4. Anything that implements the `MonadReader` type class. It’s worth understanding all four of these concepts. ### What does a Monad for functions with the same first argument do? Remember that a `Monad` is also a `Functor` and an `Applicative`. To understand the monad for `((->) e)` we will try to guess the implementations for the `Functor`, `Applicative` and `Monad` instances by looking at the types after substituting `((->) e)` into the type signatures. #### Functor instance First the `[Functor](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#t:Functor)` instance. Let’s write out the type of `[fmap](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:fmap)`. Class Functor f where fmap :: (a -> b) -> f a -> f b It is not clear from looking at this type signature, what the `Functor` instance for `((->) e)` will do. One easy way to understand what the implementation of `Functor` should be is to look at the implementation in `base`. Another way is to infer it by writing out the specialized instance signature. This is a somewhat tedious process, but it is good practice for implementing instances and understanding how they must work. The process starts by making a substitution for the type variable introduced in the type class, in this case `f`. So we substitute `f = ((->) e)`: fmap :: (a -> b) -> (((->) e) a) -> (((->) e) b) Then we simplify fmap :: (a -> b) -> (((->) e) a) -> (((->) e) b) fmap :: (a -> b) -> ((->) e a) -> ((->) e b) fmap :: (a -> b) -> (e -> a) -> (e -> b) fmap :: (a -> b) -> (e -> a) -> e -> b I am going to relabel the variables with the following substitutions, `e = a`, `a = b`, and `b = c` (because I already know what to look for ;)). fmap :: (b -> c) -> (a -> b) -> a -> c And now we can see that `fmap` for `((->) e)` is compose `[.](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:.)` fmap :: (b -> c) -> (a -> b) -> a -> c fmap f g x = f (g x) There is no other non-evil implementation for that type signature. This leads to the fun trick of trolling your coworker by writing `fmap . fmap` as `fmap fmap fmap` as in \> (fmap fmap fmap) (+1) \[Just 1, Just 2, Nothing\] \[Just 2, Just 3, Nothing\] #### Applicative instance First let’s write out `[pure](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:pure)`. pure :: a -> f a substitute `f = ((->) e)` pure :: a -> (((->) e) a) simplify pure :: a -> e -> a So we end up with a function that takes in an `a` and some random other argument `e` and returns an `a`. This must work for all `e`s and `a`s and there is no way to combine unknown types. Therefore, the only thing the function can do is return back the `a` it was given. Hence it is `[const](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:const)`: pure :: a -> e -> a pure x \_ = x Next we have `[<*>](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:-60--42--62-)` or `[ap](https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Monad.html#v:ap)`. (<\*>) :: f (a -> b) -> f a -> f b substitute `f = ((->) e)` (<\*>) :: (((->) e) (a -> b)) -> (((->) e) a) -> (((->) e) b) Simplify (<\*>) :: ((e -> (a -> b)) -> (e -> a) -> (e -> b) (<\*>) :: (e -> a -> b) -> (e -> a) -> (e -> b) (<\*>) :: (e -> a -> b) -> (e -> a) -> e -> b So the `<*>` takes two functions that both have `e` as the first argument and chains them to make a new function that takes an `e` and gives the chained output. (<\*>) :: (e -> a -> b) -> (e -> a) -> e -> b f <\*> g = \\e -> f e (g e) #### Monad instance We have already covered `[return](https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Monad.html#v:return)`: it’s just `pure`, which is just `const`. First, the type for bind: (>>=) :: m a -> (a -> m b) -> m b Substitute `m = ((->) e)` (>>=) :: (((->) e) a) -> (a -> (((->) e) b)) -> (((->) e) b) Simplify (>>=) :: (e -> a) -> (a -> (e -> b)) -> (e -> b) (>>=) :: (e -> a) -> (a -> e -> b) -> e -> b Bind is basically a flipped-around `<*>` (>>=) :: (e -> a) -> (a -> e -> b) -> e -> b g >>= f = flip f <\*> g `[join](https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Monad.html#v:join)` is more interesting. `join` flattens a two layers of a monad to one. join :: Monad m => m (m a) -> m a Let’s substitute `m = ((->) e)` join :: (((->) e) (((->) e) a))) -> (((->) e) a) Simplify join :: (((->) e) ((->) e a))) -> ((->) e a) join :: ((->) e) (e -> a)) -> (e -> a) join :: (e -> (e -> a)) -> e -> a join :: (e -> e -> a) -> e -> a There is only really one non-evil implementation for this type signature, and it is equivalent to the following: join :: (e -> e -> a) -> e -> a join f x = f x x `join` we get for free, but it is good to see how it could be implemented by hand. It’s sometimes used for creating a tuple with the same value for the first and second value. \> join (,) 1 (1, 1) ### What is Reader? You can think of `[Reader](https://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-Reader.html#t:Reader)` as being a `newtype` around `(e -> a)` newtype Reader e a = Reader { runReader :: e -> a } However, these days it is defined as a specialized version of `[ReaderT](https://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-Reader.html#t:ReaderT)`. type Reader = ReaderT Identity For all intents and purposes, it works just like the `Functor`, `Applicative` and `Monad` instances, `((->) e)`. There is really no reason to use it if `((->) e)` will suffice. ### MonadReader `[MonadReader](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html#t:MonadReader)` is the general interface for reader monads. The type class is essentially what follows: class Monad m => MonadReader r m | m -> r where ask :: m r local :: (r -> r) -> m a -> m a Let’s see what the implementation for `((->) e)` must be by substituting `m = ((->) e)` and `r = e`: instance MonadReader e ((->) e) where ask :: e -> e ask = ? local :: (e -> e) -> (e -> a) -> e -> a local = ? `[ask](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html#v:ask)` can only really be one thing: ask :: e -> e ask = id `[local](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html#v:local)` is a little trickier. It is not completely determined by the type. The documentation says it takes in a function `e -> e` that modifies the environment and a `e -> a` that uses the modified environment. Here we go: local :: (e -> e) -> (e -> a) -> e -> a local f action = action . f ### ReaderT `[ReaderT](https://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-Reader.html#t:ReaderT)` is the transformer version of `Reader`. It allows you to add the “first argument threading” capabilities of “Reader” with another `Monad`. A common choice is `ReaderT e IO`. Our example at the beginning of the article could be rewritten with `ReaderT e IO` instead of `MonadReader` but little is gained by specifying the transformer stack directly. It is more flexible to write the functions using the reader monad interface `MonadReader`. One advantage of using `ReaderT` directly is that we can take advantage of a more expressive version of `local`, mainly `[withReaderT](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader.html#v:withReaderT)` which has the following type: withReaderT :: (r' -> r) -> ReaderT r m a -> ReaderT r' m a Unlike `local` `withReaderT` can change the type of the environment from `r` to `r'`. ### Next Up That’s all for now. In a future post I’ll discuss some enhancements and compare the Reader Monad against some alternatives. > [Hacker Noon](http://bit.ly/Hackernoon) is how hackers start their afternoons. We’re a part of the [@AMI](http://bit.ly/atAMIatAMI)family. We are now [accepting submissions](http://bit.ly/hackernoonsubmission) and happy to [discuss advertising & sponsorship](mailto:partners@amipublications.com) opportunities. > To learn more, [read our about page](https://goo.gl/4ofytp), [like/message us on Facebook](http://bit.ly/HackernoonFB), or simply, [tweet/DM @HackerNoon.](https://goo.gl/k7XYbx) > If you enjoyed this story, we recommend reading our [latest tech stories](http://bit.ly/hackernoonlatestt) and [trending tech stories](https://hackernoon.com/trending). Until next time, don’t take the realities of the world for granted!