
My point here is to know, what's the reason for the different behaviour, rather than discussing the correctness of using unsafePerformIO.
The reason is this: GHC uses a lazy evaluation strategy, as opposed to fully-lazy. Under lazy evaluation, the unsafePerformIO expression in your example will be evaluated each time main is invoked. When -O is turned on, GHC performs some transformations on the code that have the effect of changing the evaluation strategy to "almost fully-lazy". That is, there will be some more sharing, but not necessarily as much as you would get in a compiler that implements fully-lazy evaluation. Indeed, even without -O, you might get a bit more sharing than you would under pure lazy evaluation. Of course, you should never write any code that depends on any of this. Cheers, Simon