ErrorT catchError in practice



我有一个非常典型的设置,在IO单子中有一组函数可以抛出错误。到目前为止,我只是通过模式匹配runerror:

的Either结果来处理monad链末尾的错误。
replLisp :: LispScope -> String -> IO String
replLisp s input = do
  result <- runErrorT (evalLisp s input)
  return $ either (id) (show) result 

我现在想添加一些错误处理到我的黑客小方案,但我有麻烦,使类型检查器高兴。

如何使用catchError?举一两个例子会有帮助的。


这是我最近的一次尝试:

catch :: [LispVal] -> IOThrowsError LispVal
catch [action rescue] = do
  eval action >>= catchError $ eval rescue

下面是使用catchError从先前对throwError的调用中恢复的示例:

import Control.Monad.Error
import Control.Monad.Identity
type MyMonad = ErrorT String Identity
runMyMonad = runIdentity . runErrorT
main = do
        let x = runMyMonad (func 5 0)
        print x
func :: Double -> Double -> MyMonad Double
func w x = do
        y <- (divider x) `catchError` (_ -> return 1)
        return (w + y)
divider :: Double -> MyMonad Double
divider x = do
        when (x == 0) (throwError "Can not divide by zero!")
        return (10 / x)

0代入进行除法,可以将1的处理结果补全,得到Right 6.0的输出。

这有帮助吗?你的问题并没有真正说明问题所在

像Either和Maybe这样的错误单子不允许你在同一个单子内观察错误:你必须运行单子才能观察它。IO中的异常是一个值得注意的例外(嗯哼),因为IO是一行的结尾……你不能再往前走了。

你有几种可能性:

  • 由于您正在编写一个迷你解释器,因此显式管理所有异常可能是一个好主意,仅对true,不可恢复的错误使用errt单子。

  • 对于任何可能出错的调用,您希望能够从中恢复,在将结果传递到当前monad之前,执行runerror并检查结果。

最新更新