如果发生错误,IORef保持值

时间:2016-05-06 17:06:01

标签: haskell exception ioref

如果在modifyIORef内发生错误,有没有办法不修改IORef值?

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

2 个答案:

答案 0 :(得分:2)

我相信您可以使用包含在异常处理程序中的modifyIORef'atomicModifyIORef'来执行此操作。我不会一般地推荐它; error调用生成供用户读取的字符串,而不是处理程序的详细信息。并且处理从“纯”代码抛出的异常的整个“不精确异常”机制需要非常谨慎才能正确使用。你几乎总是更好,确保永远不会从纯代码中抛出异常。 ExceptTEither等可以提供帮助。

答案 1 :(得分:-1)

Haskell不像其他语言(如Python和Java)那样进行错误处理。当您调用error函数时,程序将暂停。期。无法捕获错误。无法重定向或重新启动程序。 error函数引发错误,而不是异常。如果您想在Haskell中表示失败的想法,请使用MaybeEither monad。以下是使用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)

编辑: 正如dfeuer在他的评论中所指出的那样, 可以拦截GHC中的错误。但是,除非在非常具体的情况下,否则将其视为不良做法,因此仍然需要使用MaybeEither类型。