
On Mon, Sep 08, 2003 at 12:48:26PM +0100, Simon Marlow wrote:
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.
The difference is that I wasn't suggesting that these replace the existing definitions, but provide an additional more general interface (i.e. non-destructive generalization). However generalizing instances (like those of MArray) is a different situation, leading to problems with overlapping instances. Once you have instance MArray IOArray e IO instance MArray (STArray s) e (ST s) you can't define instance MonadST s m => MArray (STArray s) e m An alternative is to define functions like readSTArray :: (MonadST s m, MArray a e (ST s), Ix i) => a i e -> i -> m e readSTArray arr i = liftST (readArray arr i) but that's not ideal: you end up with two interfaces, neither of which is more general than the other.