失败`Turtle``Shell`没有抛出错误

时间:2017-12-21 13:48:45

标签: haskell exception-handling haskell-turtle

我有一个程序,用于解析程序的输出行,并产生一些输出数据结构,其中包含从这些行中提取的一些信息。为此,我使用turtle

import Turtle
import qualified Control.Foldl as F
import           Control.Monad.Except

-- Just for illustration purposes
newtype Result a = Result [a]
type Error = String

collectOutput :: (MonadIO m, MonadError Error m) => Text -> m Result
collectOutput cmd = Result <$> fold (runCmd cmd) F.list
-- Yes, I know turtle does also streaming, but I need to return all the results at the same time. Sorry...

runCmd ::Text -> Shell Result
runCmd cmd = do
    line <- inproc cmd [] empty
    tryParseOutput

现在,在尝试定义tryParseOutput时会出现问题。我想在发生错误时中止命令(用inproc cmd [] empty生成)。为此,我看到的唯一方法是使用die函数,它将抛出IOError

tryParseOutput line =
    case parseOutput line of
        Left parseErr -> die $ show parseErr
        Right res     -> return res 

但现在这意味着我需要修改collectOutput来处理IOExceptions

collectOutput :: (MonadIO m, MonadError Error m) => Text -> m Result
collectOutput cmd = do
    mRes <- liftIO $ collectOutputIO cmd
    case mRes of
        Left err -> throwError err
        Right res -> return res

collectOutputIO :: Text -> IO (Either Error Result)
collectOutputIO cmd = 
    (Right . Result <$> fold (runCmd cmd) F.list) `catch` handler
    where 
        handler :: IOException -> Either Error Result
        handler ex = show ex

虽然这有效,但我不喜欢我为解析错误抛出IO异常的事实,并且涉及一些异常捕获和案例分析。所以我想知道这是否可以以更优雅的方式解决(可能更多turtle惯用语),或者我应该忘记使用MonadError并接受IOError作为生命的事实{ {1}} shell脚本?

0 个答案:

没有答案