Issues with instance Ord (STRef s a)

STRef is a Haskell datatype that is used to represent a mutable variable reference. Purity is maintained by putting two restrictions on their use:

STRefs have an Eq instance, which tests equality of the references. Occasionally someone will ask why STRefs don’t have an Ord instance that compares by address, which would allow making a Set of STRefs. For example:

There are some reasonable answers given in that thread. For example, since GHC’s garbage collector can move objects around, the address-wise comparison of STRefs wouldn’t be stable within a call to runST.

But the problem is actually worse than that. Even with an implementation where the garbage collector never moved objects around, exposing pointer comparison would allow the creation of impure functions:

f :: () -> Bool
f () = runST (do r1 <- newSTRef 0
                 r2 <- newSTRef 0
                 return (r1 < r2))

The comparison could be succeed on the first invocation of f and fail on a subsequent one.