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

发布于 2024-10-03 16:51:45 字数 467 浏览 2 评论 0原文

我很惊讶我在任何地方都找不到这个问题的答案。

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

我的问题是,haskell ncurses 库编写者尽职尽责地检查所有调用中是否有任何错误,当有错误时,他会调用:错误“drawText:等等”。

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

如果必须的话,我会在本地修改库以不检查该函数的错误,但我讨厌这样做。我也愿意接受任何允许我在不移动光标的情况下绘制最后一个字符的解决方法,但我认为这是不可能的。

I'm surprised I couldn't find an answer to this anywhere.

I'm writing a roguelike and I'm using the ncurses library from hackage, which is a pretty good wrapper around the ncurses library. Now ncurses has this quirk where if you try to write the bottom right character, it does so, then it tries to move the cursor to the next character, then it fails because there's nowhere to move it to. It returns an error value that you can only ignore.

My problem is that the haskell ncurses library writer dutifully checks for any errors on all calls, and when there is one, he calls: error "drawText: etc etc.".

In other languages, like c or python, to get around this you are forced to ignore the error or catch and ignore the exception, but for the life of me I can't figure out how to do it in haskell. Is the error function unrecoverable?

I will modify the library locally to not check for errors on that function if I have to, but I hate to do that. I'm also open to any workaround that would allow me to draw that last character without moving the cursor, but I don't think that is possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

逆蝶 2024-10-10 16:51:45

您可以使用 Control.Exception 中的 catch 来执行此操作。但请注意,您需要位于 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!"

You can do this using catch from Control.Exception. Note, however, that you need to be in the IO monad to do this.

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!"
被你宠の有点坏 2024-10-10 16:51:45

error 应该像无限循环一样可观察到。您只能在 IO 中捕获error,这就像说“是的,如果您懂得魔法,就可以”。但是从 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

如果您不想自己编写(并且您不应该——异常代码可能非常棘手,尤其是在存在线程的情况下)。

error is supposed to be as observable as an infinite loop. You can only catch error in IO, which is like saying "yeah you can if you know magic". But from the really nice part of Haskell, pure code, it is unrecoverable, and thus it is strongly advised not to use in your code, only as much as you would ever use an infinite loop as an error code.

ncurses is being rude and making you do magic to correct it. I'd say unsafePerformIO would be warranted to clean it up. Other than that, this is largely the same as Paul's answer.

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)

Then wrap unsafeCleanup around any value that would evaluate to an error to turn it into a Maybe.

This is available in the spoon package if you don't want to write it yourself (and you shouldn't -- exception code can be really tricky, especially in the presence of threads).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文