1. import Data.IORef (IORef, newIORef, atomicModifyIORef, readIORef)
  2. import System.IO.Unsafe (unsafePerformIO)
  3. import Control.Concurrent (threadDelay)
  4. import Control.Parallel (par)
  5. import Control.DeepSeq (force, NFData)
  6.  
  7. delayed_inc :: Int -> Int
  8. delayed_inc x = (unsafePerformIO $
  9.   do
  10.     putStrLn "Incrementing variable (waiting 2 seconds)..."
  11.     threadDelay 2000000
  12.     putStrLn "Done incrementing variable."
  13.     ) `seq` (x + 1)
  14.  
  15. f :: Int -> (Int, ())
  16. f x = (delayed_inc x, ())
  17.  
  18. atomicModifyIORefPar :: (NFData a) => IORef a -> (a -> (a, b)) -> IO b
  19. atomicModifyIORefPar ioref f =
  20.   let g olddata = (let (newdata, result) = f olddata in (newdata, (result, newdata)))
  21.   in do
  22.     (result, newdata) <- atomicModifyIORef ioref g
  23.     force newdata `par` return result
  24.  
  25. main :: IO ()
  26. main =
  27.   do
  28.     ioref <- newIORef 20
  29.     putStrLn "Modifying IORef..."
  30.     atomicModifyIORefPar ioref f
  31.     putStrLn "Waiting 5 seconds..."
  32.     threadDelay 5000000
  33.     putStrLn "Reading variable..."
  34.     newiorefval <- readIORef ioref
  35.     putStrLn "Showing variable..."
  36.     putStrLn $ show newiorefval
  37.     threadDelay 5000000