To get acquainted with unsafePerformIO (how to use it and when to use it), I\'ve implemented a module for generating unique values.
Here\'s what I have:
See an another example how this fails:
module Main where
import Unique
helper :: Int -> Unique
-- noinline pragma here doesn't matter
helper x = newUnique ()
main = do
print $ helper 3
print $ helper 4
With this code the effect is the same as in ntc2's example: correct with -O0, but incorrect with -O. But in this code there is no "common subexpression to eliminate".
What's actually happening here is that the newUnique () expression is "floated out" to the top-level, because it doesn't depend on the function's parameters. In GHC speak this is -ffull-laziness (on by default with -O, can be turned off with -O -fno-full-laziness).
So the code effectively becomes this:
helperworker = newUnique ()
helper x = helperworker
And here helperworker is a thunk that can only be evaluated once.
With the already recommended NOINLINE pragmas if you add -fno-full-laziness to the command line, then it works as expected.