Kaiko Kaur
Kaiko Kaur

Reputation: 361

IORef keeping value if an error occurs

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

Answers (2)

Kwarrtz
Kwarrtz

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

dfeuer
dfeuer

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

Related Questions