为什么无法处理异常

时间:2018-12-12 07:01:06

标签: haskell

我有以下代码:

handledIO :: Int -> IO Int
handledIO x = handle (printException x) $ return $ [1, 2, 3] !! x

printException :: Int -> SomeException -> IO Int
printException x (SomeException e) = do
  print ("Exception", x, e)
  throw e

当我在ghci中键入handledIO 8时,我希望看到("Exception", 8, "*** Exception: Prelude.!!: index too large")将被打印,但实际上仅打印异常。为什么?

1 个答案:

答案 0 :(得分:12)

原因有点微妙,与Haskell的懒惰有关。

让我们使用具有相同问题的此示例版本:

EventLoop

问题是handledIO :: Int -> IO Int handledIO x = handle (printException x) $ return undefined 仅捕获在运行作为参数传递的handle操作时引发的异常。动作IO成功完成了 ,因为从未从动作中 检查return undefined。但是,当其他undefined操作尝试实际检查返回的值时(例如,尝试将其打印到控制台),则会遇到令人讨厌的惊喜。

此“ IO中的延迟异常抛出结果值”问题的一种解决方案是使用IO中的evaluate函数而不是Control.Exceptionreturn注意在evaluate操作返回之前将参数减为WHNF,因此它会触发异常:

IO

现在可以使用了

handledIO :: Int -> IO Int
handledIO x = handle (printException x) $ evaluate $ undefined

此外,您正在*Main> handledIO 10 ("Exception",10,Prelude.undefined 动作中使用throw。在进行IO动作时,throwIOIO更好。

相关问题