gpt4 book ai didi

haskell - 回滚 IO 操作

转载 作者:行者123 更新时间:2023-12-01 04:55:36 28 4
gpt4 key购买 nike

我有一个非常简单的抽象来处理一系列可以回滚的 IO 操作(在某种程度上),即如果一个操作写入一个文件,那么回滚将删除这个文件或者如果一个操作创建一个目录树,修剪这将是回滚等。

data IOAction = IOAction {
execute :: IO (),
rollback :: IO ()
}

executeAll :: [IOAction] -> IO ()
executeAll [] = return ()
executeAll (a : as) = do
execute a
executeAll as `catch` rollbackAndRethrow
where
rollbackAndRethrow :: SomeException -> IO ()
rollbackAndRethrow e = rollback a >> throw e

它几乎可以满足我的需求,但我有一种强烈的预感,有更可组合和更可靠(在异常处理的意义上)的方法来做到这一点。所以我的问题是我可以使用某个库中已知的 monad 转换器来实现相同的想法吗?

有类似的东西
writeFilesAtomically :: CanRollbackT IO ()
writeFilesAtomically = do
a1 <- (writeFile a str1) `orRollback` removeFile a
a2 <- (writeFile x str2) `orRollback` removeFile x
....

会比目前的解决方案更方便。

最佳答案

这看起来很像 WriterT monad 结合 ExceptT .你可能会做这样的事情:

orRollback action rollaction = do
eres <- liftIO $ try action
case eres of
Right res -> do
tell [rollaction]
return res
Left (e :: SomeException) -> throwE e

然后像这样调用它:
runMyComputation computation = do
(res, rolls) <- runWriterT $ runExceptT $ computation
case res of
Right r -> return r
Left e -> do
sequence_ (reverse rolls) -- Handle errors in rollbacks?
throwIO e

我没有测试它,但这个想法应该可行。你可能需要一些比 [] 更好的幺半群如果您要经常看到异常。

这不完全是因为你不能做 onRollback非 IO 操作。但这可能完全没问题。

关于haskell - 回滚 IO 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37510611/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com