Reputation: 361
Is there a way to NOT modify IORef value if error happens inside modifyIORef
?
import Data.IORef
main = do
a <- newIORef (1::Int)
-- a keeps error now, not Int
modifyIORef a (const $ error "Error forever")
val <- readIORef a -- val is error now
putStrLn $ "Result: " ++ show val -- throws error
Upvotes: 1
Views: 173
Reputation: 2753
Haskell does not do error handling in the same way that other languages, such as Python and Java, do. When you call the error
function, the program will halt. Period. The error cannot be caught. There is no way of redirecting it, or restarting the program. The error
function raises an error, not an exception. If you want to represent the idea of failure in Haskell, you use the Maybe
and Either
monads. Below is how you might implement the functionality that you want using the Either
monad.
main = do
a <- NewIORef (Right 1 :: Either String Int)
modifyIORef a (const $ Left "some execution error")
-- a now holds a "Left" value, representing an error
val <- readIORef a
-- val now holds the "Left" value
case val of
Left err -> putStrLn $ "Error: " ++ err -- prints error (if applicable)
Right val -> putStrLn $ "Result: " ++ show val -- prints value (if applicable)
EDIT:
As dfeuer kindly pointed out in his comment, it is possible to intercept errors in GHC. It is, however, considered bad practice except in very specific circumstances, so using the Maybe
and Either
types is still preferred.
Upvotes: -1
Reputation: 48611
I believe you can do this with modifyIORef'
or atomicModifyIORef'
wrapped in an exception handler. I wouldn't recommend it in general; error
calls produce strings for users to read, not detailed info for a handler. And the whole "imprecise exception" mechanism for handling exceptions thrown from "pure" code requires quite a lot of care to use correctly. You're almost always better off making sure never to throw exceptions from pure code. ExceptT
and Either
and such can help.
Upvotes: 2