🎓 A1Learner
🔍
0 of 50 lessons completed

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 result

Example

import Control.Monad.Trans.Reader
main :: IO ()
main = do
  result <- runReaderT (do a <- ask; b <- ask; return (a + b)) 15
  print result

Key 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?