Haskell: 防止数据修改

Haskell: preventing data modification

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

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

Bang 模式用于禁用惰性求值:我需要在调用 writeConfig 一个旧配置被解析并用函数 f 修改和修改 f

但是还有一个问题:想象一下f给出了一个错误。在这种情况下,writeConfig在发生错误时已经打开文件进行写入(因为它是惰性评估首先调用的),因此配置文件丢失。

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

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

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

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

如果Config是完全严格的(没有内嵌底部),你可以这样做:

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

如果不是,您可以执行 evaluate (deepseqnewCfg ()).

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