exception - 绝对强制捕获 Haskell 中的错误

标签 exception haskell

我正在使用 hs-excelx 库,它本身使用 zip-archive。 zip-archive 达到了调用 fail 的条件,在该特定上下文中,该条件的计算结果为对 error 的调用。这是纯代码中对 error 的调用。

我正在尝试检测特定文件是否实际上是 Excel 文件。实际上,我有必要在不崩溃的情况下检测到这一点,因此我编写了一个名为 isExcel 的函数来进行检测:

import qualified Data.Excelx as E

isExcel :: BS.ByteString -> Bool
isExcel = maybe False (\_ -> True) . E.toExcelx

现在,问题是这只是一种形式。如果您对不是 zip 存档的字节字符串调用 E.toExcelx,zip-archive 将简单地错误输出。

但是,我知道我在 IO 代码中调用 isExcel,因此我编写了一个 IO 函数来 try catch 如下错误:

import qualified Data.ByteString.Lazy as BS
import Control.Exception

sd :: BS.ByteString -> IO Bool
sd bs = handle handler $ do
        ie <- return $ Excel.isExcel bs
        return (ie `seq` ie)
    where
    handler :: SomeException -> IO Bool
    handler e = return False

> sd BS.empty
*** Exception: too few bytes. Failed reading at byte position 4

这是怎么回事?根据我在http://www.haskell.org/haskellwiki/Error_vs._Exception读到的内容和其他地方,我应该捕获异常并将其转换为有用的东西。我的代码中的 ie 可能是对 Bool 的 thunk,但是在 ie 上运行 seq 怎么可能留下任何未计算的内容?当我什至不知道如何强制评估一个值时,我怎么可能捕获这样的异常?我没有时间进入 zip 存档并进行适当的错误处理。

最佳答案

这里几乎没有什么问题。首先,要强制评估 IO 中的值,请使用 Control.Exception.evaluate。该函数的类型为 evaluate::a -> IO a,它基本上是一个告诉编译器强制求值的钩子(Hook)。它存在的唯一原因是启用异常处理。

接下来,您需要一些机制来实际捕获异常。您当前使用的是 handle,但是 Control.Exception.try,其类型为 try::Exception e => IO a -> IO(要么 e a ),这里使用起来可能更简单一些。这种类型有点奇怪,但这意味着,对于您指定的某些异常类型,它 try 将返回值或异常。如果计算抛出的异常不是您指定的类型(并且不能强制为该类型),try 将重新抛出该异常。

error 的调用会产生 ErrorCall 类型的异常,因此要处理您可以使用的异常

sd :: BS.ByteString -> IO Bool
sd bs = do
        ie <- try $ evaluate $ Excel.isExcel bs
        either (const False) (id) (ie :: Either ErrorCall Bool)

当然你知道isExcel只会返回True。您可以直接使用toExcel,并修改任一行以适应这一点。

至于你的问题的根源,

a `seq` a

a完全等价。它的意思是,“当你评估(第二个)a时,也评估(第一个)a”。换句话说,还是太懒了。这就是为什么您需要评估

关于exception - 绝对强制捕获 Haskell 中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21105137/

相关文章:

java - 如何在 lblText.steText() 中设置预定义消息

haskell - 在 Haskell 中计算期间只执行一次副作用

performance - 为什么list++需要扫描list左边的所有元素?

haskell - Haskell 中的自引用函数 (interleaveStreams)

C++ 有单独的可执行日志异常吗?

c# - QueryString 未正确解析

language-agnostic - 异常机制的最佳实现是什么?

ios - Swift调用Foundation函数错误时如何抛出异常?

haskell - 如何访问特定矩阵元素或具有特定索引的Haskell

haskell - 如何实现一个最优的、纯功能性的、双端优先级队列?