如何捕获(并忽略)对错误函数的调用?

时间:2010-11-22 07:14:39

标签: exception haskell exception-handling referential-transparency

我很惊讶我无法在任何地方找到答案。

我正在编写一个roguelike,我正在使用来自hackage的ncurses库,这是ncurses库的一个非常好的包装器。现在ncurses有这个怪癖,如果你试图写下右下角,它会这样做,然后它会尝试将光标移动到下一个角色,然后失败,因为没有地方可以将它移动到。它返回一个您只能忽略的错误值。

我的问题是haskell ncurses库编写者尽职地检查所有调用上的任何错误,当有一个调用时,他调用:error“drawText:etc etc.”。

在其他语言中,比如c或python,为了解决这个问题,你不得不忽略错误或捕获并忽略异常,但对于我的生活,我无法弄清楚如何在haskell中做到这一点。错误功能是不可恢复的吗?

我将在本地修改库,以便在必要时不检查该函数的错误,但我讨厌这样做。我也对任何可以让我在不移动光标的情况下绘制最后一个字符的解决方法持开放态度,但我认为这不可行。

2 个答案:

答案 0 :(得分:17)

您可以使用catch中的Control.Exception执行此操作。但请注意,您需要在IO monad中执行此操作。

import qualified Control.Exception as Exc

divide :: Float -> Float -> Float
divide x 0 = error "Division by 0."
divide x y = x / y

main :: IO ()
main = Exc.catch (print $ divide 5 0) handler
    where
        handler :: Exc.ErrorCall -> IO ()
        handler _ = putStrLn $ "You divided by 0!"

答案 1 :(得分:13)

error应该像无限循环一样可观察。你只能在error中抓住IO,就像说“如果你知道魔法就可以。”但是从Haskell的非常好的部分,纯代码,它是不可恢复的,因此强烈建议在你的代码中使用,只有你将无限循环用作错误代码。

ncurses很粗鲁,让你做魔术纠正它。我会说unsafePerformIO有必要清理它。除此之外,这与保罗的回答大致相同。

import qualified Control.Exception as Exc

{-# NOINLINE unsafeCleanup #-}
unsafeCleanup :: a -> Maybe a
unsafeCleanup x = unsafePerformIO $ Exc.catch (x `seq` return (Just x)) handler
    where
    handler exc = return Nothing  `const`  (exc :: Exc.ErrorCall)

然后将unsafeCleanup包围在任何会评估为错误的值,并将其转换为Maybe