Hi,

On 2009/03/16, at 10:04, wren ng thornton wrote:

> next r = do n <- readIORef r
>             writeIORef r (n+1)
>             return n

Now, if I use unsafeInterleaveIO:

> main = do r <- newIORef 0
>           x <-  do a <- unsafeInterleaveIO (next r)
>                    b <- unsafeInterleaveIO (next r)
>                    return (a,b)
>           ...

The values of a and b in x are entirely arbitrary, and are only set at the point when they are first accessed. They're not just arbitrary between which is 0 and which is 1, they could be *any* pair of values (other than equal) since the reference r is still in scope and other code in the ... could affect it before we access a and b, or between the two accesses.

OK, the values of a and b depend how to deconstruct x.

Moreover, let's have two pure implementations, f and g, of the same mathematical function. Even if f and g are close enough to correctly give the same output for inputs with _|_ in them, we may be able to observe the fact that they arrive at those answers differently by passing in our x. Given that such observations are possible, it is no longer safe to exchange f and g for one another, despite the fact that they are pure and give the same output for all (meaningful) inputs.

Hm, Does it means that in optimization, a compiler may replace implementation of a pure function that have different order of evaluation, so order of actions would be different in some environments?