
On Sun, 2009-03-15 at 13:02 -0700, Ryan Ingram wrote:
unsafeInterleaveIO allows embedding side effects into a pure computation. This means you can potentially observe if some pure value has been evaluated or not; the result of your code could change depending how lazy/strict it is, which is very hard to predict!
For example:
-- given f :: Integer -> Integer
main = do r <- newIORef 0 v <- unsafeInterleaveIO $ do writeIORef r 1 return 1 x <- case f v of 0 -> return 0 n -> return (n - 1) y <- readIORef r print y
-- a couple of examples: f x = 0 -- program prints "0" -- f x = x -- program prints "1"
"f" is pure. But if f is nonstrict, this program prints 0, and if it's strict, it prints 1. The strictness of a pure function can change the observable behavior of your program!
Right. If the compiler feels like changing the way it implements your program based on that factor. But `semantics' that the compiler doesn't preserve are kind of useless...
Furthermore, due to the monad laws, if f is total, then reordering the (x <- ...) and (y <- ...) parts of the program should have no effect. But if you switch them, the program will *always* print 0.
I'm confused. I though if f was strict, then my program *always* printed 1?
Also, the compiller might notice that x is never used, and that "f" is total. So it could just optimize out the evaluation of "f v" completely, at which point the program always prints 0 again; changing optimization settings modifies the result of the program.
This is why unsafeInterleaveIO is unsafe.
Well, unsafeInterleaveIO or reasoning based on overly specific assumptions about how things must be implemented, anyway. I'm not sure you've narrowed it down to usafeInterleaveIO, though. jcc