According to the introduction about ReaderT
, I can only find:
ReaderT Env IO String
And it means
...is a computation which involves reading values from some environment
of type Env (the semantics of Reader, the base monad) and performing some
IO in order to give a value of type String.
So the order of execution will become
1. ( Already has ) some environment values -- ReaderT Env
2. Do `IO` accroding to these pre-existing values -- IO a
3. Use the `IO a` values to do more computations -- IO b...z
This will requests our program has some pre-existing values as the environment, but I thought most of program need to load these environment values. Such like the database URL, debugging switcher or anything else.
Thus, we have an inverse order of execution, and which is illegal according to the Monad stack:
1. Do some `IO` to load environment settings -- IO a first !!
2. Do more `IO` according to these settings -- fill the env and do IO
The monad stack will become:
IOT Env ReaderT Env
This is illegal because the IO
monad can't be the base monad in monad stack. So, is there a proper way to initialize my program with external setting files ?
PS1. I noticed that the xmonad
compile it's settings as a part of program. I'm still not sure whether this is the only way to "load" settings...
First, the order of monads in the monad stack doesn't have anything to do with the order of actions that you're going to perform.
Second, you probably don't even need a stack here.
A typical program that deals with configuration is structured in the following way:
data Config = ...
readConfig :: IO Config
readConfig = do
text <- readFile "~/.config"
let config = ... -- do some parsing here
return config
meat :: Reader Config Answer
meat = do
-- invoke some operations, which get config automatically through the
-- monad
main = do
config <- readConfig
let answer = runReader meat config
print answer
You need a monad stack only if meat
itself needs to perform some IO (apart from reading the config). In that case, you'd have
meat :: ReaderT Config IO Answer
meat = ...
main = do
config <- readConfig
answer <- runReaderT meat config
print answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With