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 -> ...
Considering that we only need read access to the environment, we can use the reader monad
data Reader r a = Reader (r -> a) instance Monad (Reader r) where 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' 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
This allows us to do things like the following
-- Get environment ask :: Reader r r -- Modify local environment local :: (r -> r) -> Reader r a -> Reader r a main :: Reader r r main = do r <- ask -- ^ Access to the `r` value return r -- equivalent to main2 :: Reader r r main2 = ask >>= \r -> return r -- ^ return expanded here for similarity with main
What if we want both
We can use the