How to catch (and ignore) a call to the error function?
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!"
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).