Haskell ReaderT
ReaderT adds a shared read-only value to a monad. Every step in the block can read the same value, but no step can change it.
Ask reads the shared value
The block asks for 21 and doubles it. The answer is 42, not 21.
import Control.Monad.Trans.Reader
import Data.Functor.Identity
main :: IO ()
main = print (runIdentity (runReaderT (do n <- ask; return (n * 2)) 21))Asks reads one part
The shared value is a pair holding 10 and a word. The block asks for the first part and adds 5.
import Control.Monad.Trans.Reader
import Data.Functor.Identity
main :: IO ()
main = print (runIdentity (runReaderT (do n <- asks fst; return (n + 5)) (10, "hi")))ReaderT can sit over IO
ReaderT can layer its value over IO. The block triples 7 and the main program prints the result.
import Control.Monad.Trans.Reader
main :: IO ()
main = do
result <- runReaderT (do n <- ask; return (n * 3)) 7
print resultExample
import Control.Monad.Trans.Reader
main :: IO ()
main = do
result <- runReaderT (do a <- ask; b <- ask; return (a + b)) 15
print resultKey points
- ReaderT: a transformer that carries a shared read-only value.
- Use ask to read the shared value inside a ReaderT block.
- Use asks to read one part of the shared value.
- Use runReaderT to run a ReaderT block with one shared value.
- The shared value stays the same for every step in the block.
In this example, the block asks for the shared value twice, adds the two readings, and the main program prints 30. Both readings give 15, which proves the value stays the same for every step.
Note
ReaderT comes from Control.Monad.Trans.Reader, a boot library that ships with GHC.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
What does ask return inside a ReaderT block?