val x = unsafePerformIO $ readIORef x
inc x = unsafePerformIO $ modifyIORef x (1+) >> readIORef x
main = do
x
The result is 21.Edit: an explanation. GHC runs on graph reduction, and will do "normal order" reduction in the normal case. + is strict in both arguments, so (val x) will be fully evaluated before (inc x) is evaluated.
If we replace with a lazy operator like (:), then we can get different results. Here is a program which will evaluate the (inc x) first:
main = do
x
the expression is not fully evaluated until it is printed, and then it is evaluated in reverse order, so inc x runs before val x. The result is [11,11].Of course, none of this can be relied on. GHC does a lot of optimizations, and unsafe operations are unsafe.