我正在尝试捕获“纯”代码引发的自定义异常。我不了解我的程序的行为。
我正在使用GHC 8.6.3。这是我的代码:
import Control.Exception
newtype Problem = Problem String deriving Show
instance Exception Problem
foo :: Int -> Int
foo n = n + (throw $ Problem "Whoops")
baz :: IO Int
baz =
return (foo 1)
`catch` \(Problem _) -> return 100
main = do
n <- baz
print n
`catch` \(Problem msg) -> putStrLn msg
我希望第一个处理程序捕获异常,并使程序打印“ 100”。相反,它被第二个处理程序捕获并显示“ Whoops”。
为什么在main
中而不是在baz
中捕获了异常?如何在baz
中捕获异常?
答案 0 :(得分:3)
由于懒惰,foo 1
直到您实际尝试打印n
的值时才会执行。本质上,n
绑定到未经评估的重击foo 1
,而不是foo 1
的结果。
强制baz
处理异常的一种比较笨拙的方法是使用seq
;几乎肯定会有一个更优雅的解决方案。
baz = let result = foo 1
in seq result (return result) `catch` \(Problem msg) -> return 100
而且,感谢@Alec,更优雅的解决方案是在原始函数中将return
替换为Control.Exception.evaluate
。
baz :: IO Int
baz =
evaluate (foo 1)
`catch` \(Problem _) -> return 100