Reader Monad
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
, 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
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 READ/WRITE
?
We can use the State Monad which combines the ideas of the Reader
and Writer
monads
References: hackage