Haskell"例外"

Cli*_*ton 14 haskell exception-handling exception

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

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

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

data Return r e = Success r | Exception e
Run Code Online (Sandbox Code Playgroud)

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

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

ehi*_*ird 19

是的,这是一个很好的方法,它在标准库中:Return r e与...相同Either e r.您甚至可以像编写使用异常一样编写代码IO(即,无需在模式匹配的每一步中显式处理错误):Monad用于Either传播错误的实例,就像Maybemonad一样(但是具有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)
Run Code Online (Sandbox Code Playgroud)

如果mightFail amightFail b返回Left someError,那么foo a b c也将; 错误会自动传播.(这里,throwError只是一种很好的写作方式Left,使用函数Control.Monad.Error;也catchError可以捕获这些异常.)


Pet*_*ter 11

Return r e你所描述的类型是完全相同的标准型

data Either a b = Left a | Right b
Run Code Online (Sandbox Code Playgroud)

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