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
传播错误的实例,就像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)
Run Code Online (Sandbox Code Playgroud)
如果mightFail a
或mightFail 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
.
在这里,您可以找到一个显示如何使用它的示例.