Haskell中的纯异常

Dan*_*kov 6 monads haskell exception

如何在不经过Haskell的情况下使用异常IO

我有以下代码,用于在二元搜索树中插入元素,只需最少的比较,当元素是树的成员时不复制.我注意到,either作为catchLeft作为throw:

insert x t = either (const t) id (insert' x t Nothing)
    where
    insert' x E m = maybe (Right (T E x E)) (\v -> if x==v then Left E else Right (T E x E)) m
    insert' x t@(T l v r) m = if x<v
                                 then fmap (\l' -> T l' v r) (insert' x l Nothing)
                                 else fmap (\r' -> T l v r') (insert' x r (Just v))
Run Code Online (Sandbox Code Playgroud)

因此我尝试使用Control.Monad.Error希望使代码更简单来重写它,但是我弄得很乱.有什么建议?

Pau*_*son 8

这取决于你想要的例外情况.

如果您尝试从函数返回错误值(例如"未找到键"或"键已存在"),那么您应该沿着这些行使用某些内容."左"传统上用于误差值,理由是"右"是正确的结果.Error monad在这里以与"Maybe"monad相同的方式使用:当发生错误时,其余的计算都没有完成,你不必连接很多"if then else if then then ...."一起.在这种情况下,"例外"并不是特例; 您的代码必须处理它或以某种方式将其传递到下一级别.

另一方面,您可能还想捕捉不可预见的异常,例如"head []",您认为某些事情永远不会发生,但您错了.由于这些异常是不可预测的,可能是非确定性的,并且通常不适合类型系统,因此必须将它们视为IO事件.通常的模式是忽略这些异常,除了程序的最高级别,您可以尝试保存用户的工作并提供一个有用的消息,如"请报告此错误".

抛出后一种异常很容易:只需调用"错误"即可.但只能将它用于你认为不可能发生的事情; 它永远不应该是代码的正常部分.


dav*_*420 4

Hackage 上的monadLib包有一个 Exception monad(和一个 ExceptionT monad 转换器),您可以在没有 IO 的情况下使用它当您运行它时,您会得到 Either 类型的结果。