2012-07-23 14 views
4

According to the introduction about ReaderT,我只能找到:Haskell - 如何构建一个将读取一些设置文件的程序?

ReaderT Env IO String 

这也意味着

...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. 

所以执行的顺序将成为

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 

这将要求我们的节目有一定的预先存在的值为环境,但我认为大部分程序需要加载这些环境价值观。如数据库URL,调试切换器或其他任何东西。

因此,我们有一个相反的顺序执行的,并且其是非法根据单子堆栈:

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 

的单子堆栈将成为:

IOT Env ReaderT Env 

这是非法,因为monad不能成为monad堆栈中的monad基址。那么,有没有一种正确的方式来初始化我的程序与外部设置文件?

PS1。我注意到xmonad编译它的设置作为程序的一部分。我仍然不确定这是否是“加载”设置的唯一方法...

+0

看看这个类似的问题:http://stackoverflow.com/questions/11226338/missing-something-with-reader-monad-passing-the-damn-无所不在 – 2012-07-23 08:36:06

+0

读取配置文件与'读取'命令行参数没有区别。你不需要ReaderT,只需要'config < - fmap parseConfig(readFile“config”)',这与罗马人所说的'number < - fmap(read.head)getArgs'没有区别。 – applicative 2012-07-23 14:47:34

回答

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 

你需要一个单子栈只有meat本身需要(从读取配置相距)进行一些IO。在这种情况下,你必须

meat :: ReaderT Config IO Answer 
meat = ... 

main = do 
    config <- readConfig 
    answer <- runReaderT meat config 
    print answer 
+0

但是在“真实世界Haskell”一书的第18章中:“我们在IO之上使用WriterT,因为没有IOT monad变换器。当我们使用带有一个或多个monad变换器的IO monad时,IO总是处于堆栈的底部“ - 堆栈的顺序仍然有区别? – snowmantw 2012-07-23 15:46:45

+0

并感谢您的示例中的'main'函数!当我看到函数在'IO'字段中提取值并将其视为环境时,我得到了它。 – snowmantw 2012-07-23 15:55:17

+0

顺便说一下,我可以得出结论,monad变压器是没有必要的,除非在monad(例子中的读者)下的计算会使用另一个monad中的任何东西吗?因为你说过:“只有当肉本身需要执行一些IO(除了读配置)之外,你需要一个monad堆栈。“ – snowmantw 2012-07-23 16:00:50

相关问题