在Haskell中使用效果对动作进行排序的惯用法

时间:2018-02-10 20:36:46

标签: haskell optimization

我有一个工作流,我执行一个shell命令列表,然后是一个shell命令,然后是另一个shell命令列表。要求是如果任何命令失败,则永远不会执行后续命令。此外,在任何命令失败时,我想根据哪组命令失败来做某些事情。具体来说,如果“预执行”列表失败,程序应该将累积到该点的日志文件推送到某个位置(类似于“后操作”列表)。但是,如果中间的单个命令失败,我想解析其日志文件,创建一个单独的日志文件,然后推送到那时为止创建的所有日志文件。

现在,我有一个功能

import System.Exit (ExitCode (..))

sequenceActions :: String   -- log file prefix
                -> [String] -- list of shell commands
                -> IO ExitCode 

按顺序执行shell命令列表,将其stdout / stderr写入具有给定前缀的日志文件,并在任何一个命令失败时立即返回失败。此函数由运行一个命令并记录其stdout / stderr的函数构建:

runAction :: FilePath -- log file
          -> String   -- the shell command
          -> IO ExitCode

主程序是

main :: IO ()
main = do
  exitCode' <- sequenceActions "preactions_" listOfPreactions

  case exitCode' of
    ExitSuccess -> do
      runAction mainLogFile mainShellCommand >>= \exitCode -> case exitCode of
        ExitSuccess -> do
          exitCode'' <- sequenceActions "postactions_" listOfPostactions
          pushLogFiles logDestination
          exitWith exitCode''
        fail        -> parseLogFile mainLogFile -- parse out exception and create a separate log file
                    >> pushLogFiles logDestination
                    >> exitWith fail
    -- unable to run preactions
    fail        -> pushLogFiles logDestination >> exitWith fail

令我困扰的是嵌套的do块和case语句,我觉得必须有更可读和惯用的方法来实现同样的事情。经验丰富的Haskellers,有更简洁,更干净的方法吗?

0 个答案:

没有答案