Как написать функцию "retryForever" в Haskell, используя обработку исключений?
Я хотел бы создать функцию, которая может восстанавливаться после любого количества ошибок, и повторить попытку. Конечно, осмысленная обработка ошибок рассматривается в других частях программы - это последняя попытка сохранить работоспособность. Итак, я написал это:
retryForever prog = catchAny prog progRetry
where
progRetry :: SomeException -> m a
progRetry ex = do
putStrLn $ pack $ show ex
threadDelay 4000
prog
Затем я заверну свое основное действие ввода-вывода в retryForever
:
main :: IO ()
main = retryForever $ do
logger <- newLogger
-- ...
В другой части моей программы (вероятно, в другой зеленой ветке) я проверяю это следующим образом:
error "this is a TEST ERROR"
В результате чего:
: this is a TEST ERROR
CallStack (from HasCallStack):
error, called at XXXX
(и программа умирает вместо продолжения)
Обратите внимание, что я использую classy-prelude, для случаев, когда это может иметь значение, например catchAny
там не обрабатываются асинхронные исключения, что может быть проблемой здесь.
1 ответ
Когда программа не удалась, вы должны запустить программу prog
еще раз, но завернутый в retryForever
таким образом, что если он снова потерпит неудачу, вы продолжаете пытаться:
import Control.Monad.Catch(catchAll)
retryForever :: IO a -> IO a
retryForever prog = catchAll prog retry
where retry ex = do
putStrLn $ pack $ show ex
threadDelay 4000
retryForever prog