Haskell Through Example: ReaderT
Scenario: Suppose we have a config object for which we only want to pull off certain values.
import Control.Monad.Trans.Reader
data Config = Config
{ functionName :: String
, functionTimeout :: Int
, functionPermission :: Role
, functionMemorySize :: Int
}
data Role = Admin | User
mkQuery :: Monad m => ReaderT Config m [Int]
mkQuery = do
timeout <- asks functionTimeout
memorySize <- asks functionMemorySize
return [timeout, memorySize]
main :: IO ()
main = do
let config = Config "twitter-bot-function" 360 Admin 100
queryResult <- runReaderT myQuery config
print queryResult
Which will print out
[360, 10]
Hierarchy of function calls
Scenario: Suppose we have an embedded hierarchy of function calls, and we want to pull out some configuration value at the botton of this function call stack.
import Control.Monad.Trans.Reader
data Config = Config { password :: String }
top :: Monad m => ReaderT Config m String
top = middle
middle :: Monad m => ReaderT Config m String
middle = bottom
bottom :: Monad m => ReaderT Config m String
bottom = asks password
main :: IO ()
main = do
let c = Config "password1234"
res <- runReaderT top c
print res
Which will print out
password1234
Environment with nested values
Scenario: Suppose we have a environment with nested values, and we want to pull off certain values.
module Main where
import Control.Monad.Trans.Reader
data Env = MkEnv
{ rootPassword :: Text
, user :: User
} deriving (Eq, Show)
data User = User
{ name :: Text
, address :: Text
} deriving (Eq, Show)
myQuery :: Monad m => ReaderT Env m [Text]
myQuery = do
rootPword <- asks rootPassword
userName <- asks $ name . user
userAddress <- asks $ address . user
return [rootPword, userName, userAddress]
main :: IO ()
main = do
let c = MkEnv "password" (User "Pompeii" "Rome")
query <- runReaderT myQuery c
print query
Which will print out
["password", "Pompeii", "Rome"]