如何使用异常处理在Haskell中编写“ retryForever”函数?

bba*_*ker 3 haskell exception classy-prelude

我想创建一个可以从合理的错误中恢复的函数,然后重试。当然,程序的其他部分还包含对错误的有意义的处理-这是使事情保持正常运转的最后努力。所以我这样写:

retryForever prog = catchAny prog progRetry
  where
    progRetry :: SomeException -> m a
    progRetry ex = do
      putStrLn $ pack $ show ex
      threadDelay 4000
      prog
Run Code Online (Sandbox Code Playgroud)

然后,将主要的IO操作包装在retryForever

main :: IO ()
main = retryForever $ do
  logger <- newLogger
  -- ...
Run Code Online (Sandbox Code Playgroud)

在程序的另一部分(可能是另一个绿色线程)中,我使用以下方法进行测试:

error "this is a TEST ERROR"
Run Code Online (Sandbox Code Playgroud)

导致:

: this is a TEST ERROR
CallStack (from HasCallStack):
  error, called at XXXX
Run Code Online (Sandbox Code Playgroud)

(程序死掉而不是继续)

请注意,对于可能很重要的情况,例如catchAny在其中不处理异步异常的情况下,我正在使用classy-prelude ,这很可能是此处的问题。

Wil*_*sem 5

当程序失败时,您应该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
Run Code Online (Sandbox Code Playgroud)