Haskell:阻止数据修改

时间:2015-07-18 18:48:49

标签: haskell lazy-evaluation

我有以下代码来完成更改配置文件的工作:

mutateConfig :: (Config -> Config) -> IO ()
mutateConfig f = do
    !cfg <- readConfig
    let !newCfg = f cfg
     in writeConfig newCfg

Bang模式用于禁用延迟评估:我需要在使用函数f解析和修改旧配置之后将writeConfig称为

但仍有问题:假设f出错。在这种情况下,当发生错误时,writeConfig已经打开了要写入的文件(因为它是由惰性求值首先调用的),因此配置文件会丢失。

我试图从IO monads组成一个简单的逐步逻辑(为了防止数据丢失),像这样

!cfg <- readConfig
newCfg <- return $ f cfg
writeConfig newCfg

但这也不起作用(我有点期待)。

实现这一目标的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

如果Config完全严格(没有嵌入底部),您可以这样做:

do
    cfg <- readConfig
    let newCfg = f cfg
    evaluate newCfg
    writeConfig newCfg

如果不是,您可以执行evaluate ( deepseq newCfg ())之类的操作。

但还有另一个问题:通常,写入文件可能会因I / O错误而失败(例如因为磁盘已满)。为避免这种情况,您可以写入临时文件,并在最后将rename写入真实目标。这样做可以保证只有在写入过程中没有错误时才覆盖配置。