    -- | This module extends "Data.IORef" with operations forcing the value written to the IORef.
    --   Some of these functions are available in later versions of GHC, but not all.
    module Data.IORef.Extra(
        module Data.IORef,
        writeIORef', atomicWriteIORef',
        atomicModifyIORef_, atomicModifyIORef'_
        ) where

    import Data.IORef
    import Control.Exception

    -- | Evaluates the value before calling 'writeIORef'.
    writeIORef' :: IORef a -> a -> IO ()
    writeIORef' :: forall a. IORef a -> a -> IO ()
    writeIORef' IORef a
    ref a
    x = do
        a -> IO a
    forall a. a -> IO a
    evaluate a
    x
        IORef a -> a -> IO ()
    forall a. IORef a -> a -> IO ()
    writeIORef IORef a
    ref a
    x

    -- | Evaluates the value before calling 'atomicWriteIORef'.
    atomicWriteIORef' :: IORef a -> a -> IO ()
    atomicWriteIORef' :: forall a. IORef a -> a -> IO ()
    atomicWriteIORef' IORef a
    ref a
    x = do
        a -> IO a
    forall a. a -> IO a
    evaluate a
    x
        IORef a -> a -> IO ()
    forall a. IORef a -> a -> IO ()
    atomicWriteIORef IORef a
    ref a
    x

    -- | Variant of 'atomicModifyIORef' which ignores the return value
    atomicModifyIORef_ :: IORef a -> (a -> a) -> IO ()
    atomicModifyIORef_ :: forall a. IORef a -> (a -> a) -> IO ()
    atomicModifyIORef_ IORef a
    r a -> a
    f = IORef a -> (a -> (a, ())) -> IO ()
    forall a b. IORef a -> (a -> (a, b)) -> IO b
    atomicModifyIORef IORef a
    r ((a -> (a, ())) -> IO ()) -> (a -> (a, ())) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \a
    v -> (a -> a
    f a
    v, ())

    -- | Variant of 'atomicModifyIORef'' which ignores the return value
    atomicModifyIORef'_ :: IORef a -> (a -> a) -> IO ()
    atomicModifyIORef'_ :: forall a. IORef a -> (a -> a) -> IO ()
    atomicModifyIORef'_ IORef a
    r a -> a
    f = IORef a -> (a -> (a, ())) -> IO ()
    forall a b. IORef a -> (a -> (a, b)) -> IO b
    atomicModifyIORef' IORef a
    r ((a -> (a, ())) -> IO ()) -> (a -> (a, ())) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \a
    v -> (a -> a
    f a
    v, ())