实际中出现错误catchError

时间:2011-04-14 06:25:26

标签: haskell error-handling

我有一个非常典型的设置,IO monad中有一组可以抛出错误的函数。到目前为止,我刚刚通过模式匹配runErrorT的结果来处理monad链末尾的错误:

replLisp :: LispScope -> String -> IO String
replLisp s input = do
  result <- runErrorT (evalLisp s input)
  return $ either (id) (show) result 

我现在想为我的Hacked小方案添加一些错误处理,但是我很难让类型检查器开心。

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


这是我最近的尝试:

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

2 个答案:

答案 0 :(得分:7)

以下是使用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的输出。

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

答案 1 :(得分:0)

像Either和Maybe这样的错误monad不允许你在同一个monad中观察错误:你必须运行monad才能观察它。 IO中的异常是一个值得注意的例外(咳咳),因为IO是行的结尾......你不能再去那里了。

您有几种可能性:

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

  • 对于您希望能够从中恢复的任何错误的调用,执行runErrorT并检查该结果,然后在当前monad中传递结果。