How to catch (and ignore) a call to the error function?

后端 未结 2 1016
囚心锁ツ
囚心锁ツ 2021-02-18 18:30

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 arou

相关标签:
2条回答
  • 2021-02-18 18:41

    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!"
    
    0 讨论(0)
  • 2021-02-18 19:01

    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).

    0 讨论(0)
提交回复
热议问题