Hi all,

This e-mail is about two things.

===========================================================

The first is the definition of "unsafeIOtoST" in ST.hs.
Currently the definition is:

  unsafeIOtoST :: IO a -> ST s a
  unsafeIOtoST = returnST . unsafePerformIO

I think the following definition makes more sense:

  unsafeIOtoST :: IO a -> ST s a
  unsafeIOtoST io =
    unsafePerformIO $
      do a <- io
         return (returnST a)

This is because one probably wants to have all side effects
coming from IO at exactly that spot in the ST computation
(otherwise it wouldn't make any sense to lift it into ST).
I am thinking of something like this:

  do ...
     unsafeIOtoST (writeIORef ref "cow")
     ...

This does not make any sense with the first definition.

===========================================================

And second, I think I found a bug in the implementation of
the strict ST monad. I am not sure, but I did the following:

  1. I started with an IO computation only using
     IORef's that I wanted to make pure. Everything worked
     correctly.

  2. I changed all IO's to (ST s)'s. I changed all
     IORef's to STRef's. I added a big runST around my
     function. Now I got incorrect results.

  3. I spent lots of time debugging.

  4. I made my own module MyST.hs, where I implement
     ST and STRef using IO and IORef (see attachment).

  5. I imported MyST instead of ST. Now everything works
     again.

My question is: is this behavior possible with a correct
implementation of the strict ST monad?

===========================================================

Regards,
Koen.

--
Koen Claessen         http://www.cs.chalmers.se/~koen     
phone:+46-31-772 5424      e-mail:[EMAIL PROTECTED]
-----------------------------------------------------
Chalmers University of Technology, Gothenburg, Sweden

===========================================================

module MyST
  ( ST
  , STRef
  , newSTRef
  , readSTRef
  , writeSTRef
  , runST
  )
 where
 
import IOExts
  ( IORef
  , newIORef
  , readIORef 
  , writeIORef
  , unsafePerformIO
  )

newtype ST s a
  = ST (IO a)

unST :: ST s a -> IO a
unST (ST io) = io

instance Functor (ST s) where
  fmap f (ST io) = ST (fmap f io)

instance Monad (ST s) where
  return a    = ST (return a)
  ST io >>= k = ST (do a <- io ; unST (k a))

newtype STRef s a
  = STRef (IORef a)
  
instance Eq (STRef s a) where
  STRef r1 == STRef r2 = r1 == r2

newSTRef :: a -> ST s (STRef s a)
newSTRef a = ST (STRef `fmap` newIORef a)

readSTRef :: STRef s a -> ST s a
readSTRef (STRef r) = ST (readIORef r)

writeSTRef :: STRef s a -> a -> ST s ()
writeSTRef (STRef r) a = ST (writeIORef r a)

runST :: (forall s . ST s a) -> a
runST st = unsafePerformIO (unST st)


Reply via email to