This post will cover the . It will mostly be an exercise in how to specialize types, simplify the substitutions and come up with the only reasonable implementation. foundations learning Motivation The monad, or more generally the interface, solves the problem of threading the same configuration to many functions. Reader MonadReader -- Imagine this is a directorytype Config = FilePath load :: Config -> String -> IO Stringload config x = readFile (config ++ x) loadRevision :: Config -> Int -> IO StringloadRevision config x = load config ("history" ++ show x ++ ".txt") loadAll :: Config -> Int -> String -> IO (String, String)loadAll config x y = doa <- load config yb <- loadRevision config xreturn (a, b) If you look at you’ll see 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. loadAll config So instead of threading the to each function, we can rewrite this using and the configuration will get passed implicitly. To retrieve the configuration, we call : config MonadReader ask -- Imagine this is a directorytype Config = FilePath load :: (MonadReader Config m, MonadIO m) => String -> m Stringload x = doconfig <- askliftIO $ readFile (config ++ x) loadRevision :: (MonadReader Config m, MonadIO m) => Int -> m StringloadRevision x = load ("history" ++ show x ++ ".txt") loadAll :: (MonadReader Config m, MonadIO m) => Int -> String -> m (String, String)loadAll x y = doa <- load yb <- loadRevision xreturn (a, b) If you look at the intermediate functions and we no longer have to take in and pass the config around. However the “leaf” function 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. loadRevision loadAll load ( (->) e), Reader, ReaderT and MonadReader When Haskellers mention the “reader monad” they could be referring to one of four related things: The instance for functions with the same first argument, which is written somewhat inscrutably as (which I think of as ). Monad ((->) e) (e ->) type Reader = ReaderT Identity The type ReaderT Anything that implements the type class. MonadReader It’s worth understanding all four of these concepts. What does a Monad for functions with the same first argument do? Remember that a is also a and an . To understand the monad for we will try to guess the implementations for the , and instances by looking at the types after substituting into the type signatures. Monad Functor Applicative ((->) e) Functor Applicative Monad ((->) e) Functor instance First the instance. Let’s write out the type of . [Functor](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#t:Functor) [fmap](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:fmap) Class Functor f wherefmap :: (a -> b) -> f a -> f b It is not clear from looking at this type signature, what the instance for will do. Functor ((->) e) One easy way to understand what the implementation of should be is to look at the implementation in . 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. Functor base 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, , , and (because I already know what to look for ;)). e = a a = b b = c fmap :: (b -> c) -> (a -> b) -> a -> c And now we can see that for is compose fmap ((->) e) [.](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:.) fmap :: (b -> c) -> (a -> b) -> a -> cfmap 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 as as in fmap . fmap fmap fmap fmap > (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 and some random other argument and returns an . This must work for all s and s and there is no way to combine unknown types. Therefore, the only thing the function can do is return back the it was given. Hence it is : a e a e a a [const](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:const) pure :: a -> e -> apure x _ = x Next we have or . [<*>](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:-60--42--62-) [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 as the first argument and chains them to make a new function that takes an and gives the chained output. <*> e e (<*>) :: (e -> a -> b) -> (e -> a) -> e -> bf <*> g = \e -> f e (g e) Monad instance We have already covered : it’s just , which is just . [return](https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Monad.html#v:return) pure 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 -> bg >>= f = flip f <*> g is more interesting. flattens a two layers of a monad to one. [join](https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Monad.html#v:join) join 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 -> ajoin :: (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 -> ajoin f x = f x x 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 > join (,) 1(1, 1) What is Reader? You can think of as being a around [Reader](https://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-Reader.html#t:Reader) newtype (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 , and instances, . There is really no reason to use it if will suffice. Functor Applicative Monad ((->) e) ((->) e) MonadReader is the general interface for reader monads. The type class is essentially what follows: [MonadReader](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html#t:MonadReader) class Monad m => MonadReader r m | m -> r whereask :: m rlocal :: (r -> r) -> m a -> m a Let’s see what the implementation for must be by substituting and : ((->) e) m = ((->) e) r = e instance MonadReader e ((->) e) whereask :: e -> eask = ? local :: (e -> e) -> (e -> a) -> e -> alocal = ? can only really be one thing: [ask](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html#v:ask) ask :: e -> eask = id is a little trickier. It is not completely determined by the type. The documentation says it takes in a function that modifies the environment and a that uses the modified environment. [local](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html#v:local) e -> e e -> a Here we go: local :: (e -> e) -> (e -> a) -> e -> alocal f action = action . f ReaderT is the transformer version of . It allows you to add the “first argument threading” capabilities of “Reader” with another . A common choice is . Our example at the beginning of the article could be rewritten with instead of but little is gained by specifying the transformer stack directly. It is more flexible to write the functions using the reader monad interface . [ReaderT](https://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-Reader.html#t:ReaderT) Reader Monad ReaderT e IO ReaderT e IO MonadReader MonadReader One advantage of using directly is that we can take advantage of a more expressive version of , mainly which has the following type: ReaderT local [withReaderT](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader.html#v:withReaderT) withReaderT :: (r' -> r) -> ReaderT r m a -> ReaderT r' m a Unlike can change the type of the environment from to . local withReaderT r 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. is how hackers start their afternoons. We’re a part of the family. We are now and happy to opportunities. Hacker Noon @AMI accepting submissions discuss advertising & sponsorship To learn more, , , or simply, read our about page like/message us on Facebook tweet/DM @HackerNoon. If you enjoyed this story, we recommend reading our and . Until next time, don’t take the realities of the world for granted! latest tech stories trending tech stories