Сбой `Turtle` `Shell` без выкидывания ошибки

У меня есть программа, которая предназначена для анализа выходных строк программы и создания некоторой структуры выходных данных, которая содержит некоторую информацию, извлеченную из этих строк. Для этого я использую 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

Хотя это работает, мне не нравится тот факт, что я генерирую исключение ввода-вывода для ошибки синтаксического анализа, и есть некоторая перехват исключительной ситуации и анализ случая. Поэтому мне было интересно, может ли это быть решено более элегантным способом (может быть, более turtle идиоматический), или я должен забыть об использовании MonadError и принять IOError как факт жизни turtle сценарии оболочки?

0 ответов

Другие вопросы по тегам