Suppose we have a function that requires knowing the environment

start :: Env -> ...


It will be pretty common to require this throughout the code.

startLogger :: Env -> ...
startDatabase :: Env -> ...


data Reader r a = Reader (r -> a)

return a = ReaderG $\_ -> a (>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b) ReaderG f >>= g = ReaderG$ \r -> let a = f r
f' = g a
in f' r


Observe that the variable r passed into both functions f, f' is the same.

This shows that we reuse the same r value, which could be the environment, a configuration and so on.

This is used as a READ-only value. We cannot update it, as again (>>=) only gives us a.

This allows us to do things like the following

-- Get environment

-- Modify local environment
local :: (r -> r) -> Reader r a -> Reader r a

main = do
r <- ask -- ^ Access to the r value
return r

-- equivalent to

What if we want both READ/WRITE?
We can use the which combines the ideas of the Reader and Writer monads