[Haskell-cafe] IO and State
Ben Rudiak-Gould
Benjamin.Rudiak-Gould at cl.cam.ac.uk
Thu Nov 11 10:57:42 EST 2004
Iavor S. Diatchki wrote:
> In GHC the whole program stops when the main thread exits.
> So if the law I was talking about holds, this program should
> never terminate, as it will forever loop in 'reader'.
> However since there is a concurrent thread running that can modify
> the state, if 'reader' is interrupted between the two readSTRefs
> we will get different values for 'x' and 'y' and 'reader' will stop.
> I tried that in GHC and it stops after a little while, so the law does
> not hold.
I would say that the law holds in one direction and not the other. It's
safe to replace
do x <- readSTRef r
y <- readSTRef r
with
do x <- readSTRef r
let y = x
but not the other way around. The semantics for concurrency don't
guarantee that a task switch will /never/ happen between two calls of
readIORef, but they don't guarantee that a task switch will /ever/
happen, either, so relying on your sample application terminating is
non-portable. Therefore optimizing it in such a way that it never
terminates is safe.
If it's important to distinguish ST actions which can be treated as IO
from others which can't, you can introduce a type class
class PrivateState s where {}
and a new function
newPureSTRef :: forall a s. PrivateState s => a -> ST s (Ref s a)
newPureSTRef = newRef
There don't need to be any instances of PrivateState; the only important
thing is that RealWorld isn't an instance. Any code which uses a Ref
created by newPureSTRef is restricted to the PrivateState space and
therefore can't be used as part of an IO action. runST would be given
the more general type
runST :: forall a. (forall s. PrivateState s => ST s a) -> a
which would work for pure ST and ordinary (IO-embeddable) ST actions.
stToIO would retain its current type, and so would not work with pure ST
actions. Your equivalence would apply in both directions to any action
of type (forall s. PrivateState s => ST s a).
I don't think this careful approach is necessary in practice, but I hope
the fact that it can be done [*] makes the merging of ST and IO look
more reasonable.
-- Ben
[*] Except how would you prevent the user from declaring an instance for
PrivateState RealWorld? Oh well. It can be done /in principle/. :-)
More information about the Haskell-Cafe
mailing list