sno*_*ntw 4 haskell functional-programming monad-transformers
根据介绍ReaderT,我只能找到:
ReaderT Env IO String
Run Code Online (Sandbox Code Playgroud)
这意味着
...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.
Run Code Online (Sandbox Code Playgroud)
因此执行的顺序将成为
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
Run Code Online (Sandbox Code Playgroud)
这将要求我们的程序有一些预先存在的值作为环境,但我认为大多数程序需要加载这些环境值.如数据库URL,调试切换器或其他任何东西.
因此,我们有一个相反的执行顺序,根据Monad堆栈,这是非法的:
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
Run Code Online (Sandbox Code Playgroud)
monad堆栈将变为:
IOT Env ReaderT Env
Run Code Online (Sandbox Code Playgroud)
这是非法的,因为IOmonad不能是monad堆栈中的基本monad.那么,有没有一种正确的方法来使用外部设置文件初始化我的程序?
PS1.我注意到xmonad 编译它的设置作为程序的一部分.我还不确定这是否是"加载"设置的唯一方法......
Rom*_*aka 11
首先,monad堆栈中monad的顺序与你要执行的操作顺序没有任何关系.
其次,你可能甚至不需要堆栈.
处理配置的典型程序按以下方式构建:
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
Run Code Online (Sandbox Code Playgroud)
只有在meat自身需要执行某些IO(除了读取配置)之外,您才需要monad堆栈.在那种情况下,你有
meat :: ReaderT Config IO Answer
meat = ...
main = do
config <- readConfig
answer <- runReaderT meat config
print answer
Run Code Online (Sandbox Code Playgroud)