
More suggestions:
1) Pursuing the view that this thing identifies a special ST-style state included in the IO monad, we could view the IO state stuff as a special case of the ST stuff, changing
newtype IORef a = IORef (STRef IOState a) newtype IOArray i e = IOArray (STArray IOState i e) newtype IOUArray i e = IOUArray (STUArray RealWorld i e)
(currently exported opaquely) to
type IORef = STRef IOState type IOArray = STArray IOState type IOUArray = STUArray IOState
so that there would only be one type of reference.
This constrains the implementations of IORef and STRef to be the same (obviously). I can't immediately see any benefit from using different implementations for these two types, so maybe it's not an issue.
2) For additional genericity, define a class
class MonadST s m | m -> s where liftST :: Control.Monad.ST.ST s a -> m a
[snip]
then all the operations lift to all such monads, e.g.
readSTRef :: MonadST s m => STRef s a -> m a readSTRef r = liftST (Data.STRef.readSTRef r)
Same argument as for MonadIO: I don't like the idea of generalising all the ST functions, and just generalising some of them would be inconsistent, so don't generalise any of them. Providing MonadST and liftST is fine, though. Cheers, Simon