[Haskell-cafe] unsafeInterleaveST (and IO) is really unsafe [was: meaning of "referential transparency"]

Tom Ellis tom-lists-haskell-cafe-2013 at jaguarpaw.co.uk
Thu Apr 11 10:05:34 CEST 2013


On Thu, Apr 11, 2013 at 12:49:40PM +1200, Richard A. O'Keefe wrote:
> On 10/04/2013, at 2:45 PM, <oleg at okmij.org> wrote:
> ... unsafeInterleaveST is really unsafe ...
> 
> > import Control.Monad.ST.Lazy (runST)
> > import Control.Monad.ST.Lazy.Unsafe (unsafeInterleaveST)
> > import Data.STRef.Lazy
> > 
> > bad_ctx :: ((Bool,Bool) -> Bool) -> Bool
> > bad_ctx body = body $ runST (do
> >   r <- newSTRef False
> >   x <- unsafeInterleaveST (writeSTRef r True >> return True)
> >   y <- readSTRef r
> >   return (x,y))
> > 
> > t1 = bad_ctx $ \(x,y) -> x == y   -- True
> > t2 = bad_ctx $ \(x,y) -> y == x   -- False

[...]
> I don't understand what it does or *how* it breaks this code.  Does it
> involve side effects being reordered in some weird way?

As I understand it, unsafeInterleaveST defers the computation of x, so

  * if x is forced before y, then "writeSTRef r True"
    is run before "readSTRef r", thus the latter yields "True"

  * if y is forced before x, then "writeSTRef r True" is run after
    "readSTRef r", thus the latter yields "False"

Tom



More information about the Haskell-Cafe mailing list