Haskell“例外”

时间:2012-05-16 02:49:22

标签: exception haskell exception-handling

我有一组用户,组以及用户和组之间的映射。我有各种操作这些集合的函数,但是不应该为不存在的用户添加用户< - >组映射,也不能删除仍然将用户作为成员的组等。

所以基本上我希望这些函数抛出必须由调用者明确处理的“异常”。

我首先想到的是返回这样的东西:

data Return r e = Success r | Exception e

如果调用者未能与Exception进行模式匹配,他们将希望获得编译器警告,或者在出现问题时至少会出现明显的运行时错误。

这是最好的方法,是否有预先打包的解决方案?注意我需要抛出并捕获纯代码中的“异常”,而不是IO Monad。

2 个答案:

答案 0 :(得分:19)

是的,这是一种很好的方法,它位于标准库中:Return r eEither e r相同。您甚至可以编写代码,就像在IO中使用异常一样(即,无需使用模式匹配在每个步骤中显式处理错误):Monad Either实例传播错误,就像Maybe monad一样(但在出现错误的情况下附加e值)。例如:

data MyError
    = Oops String
    | VeryBadError Int Int

mightFail :: T -> Either MyError Int
mightFail a = ...

foo :: T -> T -> Int -> Either MyError Int
foo a b c = do
    x <- mightFail a
    y <- mightFail b
    if x == y
        then throwError (VeryBadError x y)
        else return (x + y + c)

如果mightFail amightFail b返回Left someError,那么foo a b c也会;错误会自动传播。 (在这里,throwError只是使用Control.Monad.Error中的函数编写Left的好方法;还有catchError来捕获这些异常。)

答案 1 :(得分:11)

您描述的Return r e类型正是标准类型

data Either a b = Left a | Right b

您可能希望使用mtl包的所谓"error monad"(更合适的名称是“exception monad”)。 (或者,如果您不想使用mtl,则monadLib包中有ExceptionT。这允许您通过调用throwErrorcatchError在纯代码中进行错误处理。 Here您可以找到一个展示如何使用它的示例。