在Haskell 2010标准的第7.3节中,我阅读了以下内容:
I / O monad包含一个简单的异常处理系统。任何I / O. 操作可能会引发异常,而不是返回结果。
I / O monad中的异常由IOError类型的值表示。 这是一种抽象类型:它的构造函数对用户是隐藏的。 IO库定义构造和检查IOError的函数 值。创建IOError值的唯一Prelude函数是 userError。用户错误值包括描述错误的字符串。
Haskell 98标准的文本几乎相同。
在实践中,我经常看到来自Control.Exception.Base:
的SomeException的catch构造SomeException类型是异常类型层次结构的根。 当抛出类型e的异常时,它就在后面 封装在SomeException中。
使用GHC进行的一项小型实验表明,IOException也封装在SomeException中。
import GHC.IO(failIO)
import Control.Exception(catch, SomeException(..))
main :: IO ()
main = (x >>= print) `catchAll` \e -> print ("caught: " ++ show e)
x :: IO Int
x = failIO "Failed to get x!"
catchAll :: IO a -> (SomeException -> IO a) -> IO a
catchAll = catch
运行以上程序给我们:
caught: user error (Failed to get x!)
这如何符合标准?它是Haskell标准的GHC特定扩展吗?
答案 0 :(得分:2)
GHC仍然拥有IOError
等报告中描述的所有机制。
然而,在实践中发现非常有限,因为人们需要为不精确和后来的异步异常引入新的异常类型。因此诞生了一个新的模块来统一管理所有这些类型。然而,这个模块的问题是,虽然它扩展了可用的异常范围,但它以固定的方式实现了这一点。因此诞生了对扩展的可扩展机制的渴望。 Simon Marlow(http://community.haskell.org/~simonmar/papers/ext-exceptions.pdf)在2006年的一篇论文中提供了设计,动机和实施。
这将我们带到了今天我们所熟悉和喜爱的Control.Exception
模块。
正如论文所描述的那样,该库基本上是在用户空间中实现的,只需要一些语言级结构,如存在性和Typeable
。