[Haskell] Re: ST/STRef vs. IO/IORef

Remi Turk rturk at science.uva.nl
Fri Aug 5 05:40:56 EDT 2005

On Fri, Aug 05, 2005 at 08:04:53AM +0200, Till Mossakowski wrote:
> Sebastian Sylvan wrote:
> >Hmmm... Wasn't that what he said?
> I disagree with the equation "primitives = unsafe" that
> is implicit in sentence
>  to be implemented _efficiently_, also needs
>  something like unsafePerformIO (or even lower-level unsafe
>  mutable state primitives).
> The point is that ST uses *safe* primitives, and not "something
> like unsafePerformIO".

Ah, I think I understand what we're disagreeing about exactly
now. We're understanding "primitive" to mean different things :)

You're seeing runST, newSTRef, writeSTRef etc as primitives, is
that correct? I see them as the public interface to something
which is implemented in something else. That is, just like
the "memo" function (deprecated, from the package util) is a safe
interface (memo is nicely referentially transparant) to a piece
of functionality implemented using unsafe primitives
(unsafePerformIO), the ST monad a perfectly safe abstraction
built on top of not-so-safe primitives. And with primitives I
mean unsafePerformIO in my previously attached implementation. In
GHC's implementation, this is even more clear:

  writeSTRef :: STRef s a -> a -> ST s ()
  writeSTRef (STRef var#) val = ST $ \s1# ->
      case writeMutVar# var# val s1#      of { s2# ->
          (# s2#, () #) }
  {-# INLINE runST #-}
  runST :: (forall s. ST s a) -> a
  runST st = runSTRep (case st of { ST st_rep -> st_rep })
  {-# NOINLINE runSTRep #-}
  runSTRep :: (forall s. STRep s a) -> a
  runSTRep st_rep = case st_rep realWorld# of (# _, r #) -> r

There is a lot of messing around with state here. Actually,
runST(Rep) is remarkably similiar to unsafePerformIO:

  {-# NOINLINE unsafePerformIO #-}
  unsafePerformIO	:: IO a -> a
  unsafePerformIO (IO m) = case m realWorld# of (# _, r #)   -> r

On Fri, Aug 05, 2005 at 08:12:36AM +0200, Till Mossakowski wrote:
> Remi Turk wrote:
> >In a final attempt to convince someone of I'm not exactly sure
> >what, I attached a simple implementation of the ST monad in
> >terms of unsafePerformIO + IORef + IOArray.
> OK, but you have to reason about this implementation to show that
> it is safe (which may be difficult because unsafePerformIO makes
> reasoning extremely difficult), while the primitives of ST are
> more easily proved to be safe.

Though it's certainly not a formal proof, it seems to be ok by
both the "can you imagine an alternative, possibly horribly slow,
but pure implementation" and by the "does it perform no observable
side-effects and does it always yield the same value" criteria.

However, this is almost what I meant: Assume you'd really like to
have (1) the efficient histogram function from my previous message
and (2) an efficient implementation of ixmap.

You could implement both using unsafePerformIO + IOArray's and
still be perfectly safe. However, you'd have to prove it's safe
_twice_, both for (1) and for (2).

The superior alternative is to first implement the ST monad using
unsafePerformIO + IOArray's, proof that to be safe, and then
implement (1) and (2) using ST without having to think about
safety anymore.

Happy hacking,

Remi "We're probably agreeing 99.9% anyway" Turk

Nobody can be exactly like me. Even I have trouble doing it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://www.haskell.org//pipermail/haskell/attachments/20050805/6a5bed2e/attachment.bin

More information about the Haskell mailing list