import Data.IORef (IORef, newIORef, atomicModifyIORef, readIORef) import System.IO.Unsafe (unsafePerformIO) import Control.Concurrent (threadDelay) import Control.Parallel (par) import Control.DeepSeq (force, NFData) delayed_inc :: Int -> Int delayed_inc x = (unsafePerformIO $ do putStrLn "Incrementing variable (waiting 2 seconds)..." threadDelay 2000000 putStrLn "Done incrementing variable." ) `seq` (x + 1) f :: Int -> (Int, ()) f x = (delayed_inc x, ()) atomicModifyIORefPar :: (NFData a) => IORef a -> (a -> (a, b)) -> IO b atomicModifyIORefPar ioref f = let g olddata = (let (newdata, result) = f olddata in (newdata, (result, newdata))) in do (result, newdata) <- atomicModifyIORef ioref g force newdata `par` return result main :: IO () main = do ioref <- newIORef 20 putStrLn "Modifying IORef..." atomicModifyIORefPar ioref f putStrLn "Waiting 5 seconds..." threadDelay 5000000 putStrLn "Reading variable..." newiorefval <- readIORef ioref putStrLn "Showing variable..." putStrLn $ show newiorefval threadDelay 5000000