Thu, 7 Feb 2002 09:52:57 +0100 (MET)
I have a solution...
data Ref m a = MkRef
get :: m a,
set :: a -> m (),
modify :: (a -> a) -> m ()
-- m somehow uses 'rep' internally
class (Monad rep, Monad m) => LiftedMonad rep m where
lift :: rep a -> m a;
instance LiftedMonad (ST s) (ST s) where
lift = id;
instance LiftedMonad (ST s) TransformedMonad where
liftRef :: (LiftedMonad rep m) => Ref rep a -> Ref m a;
liftRef ref = ...
newSTRef :: a -> (ST s) (Ref (ST s) a);
getLifted :: (LiftedMonad rep m) => Ref rep a -> m a;
getLifted = get . liftRef;
setLifted :: (LiftedMonad rep m) => Ref rep a -> a -> m ();
setLifted = set . liftRef;
modifyLifted :: (LiftedMonad rep m) => Ref rep a -> (a -> a) -> m ();
modifyLifted = modify . liftRef;
Now when you need a new Ref, use newSTRef, and when you need to use the
Ref, use getLifted, setLifted and modifyLifted. They'll work equally well
with (ST s) as with TransformedMonad.
Hmm. Yes. But you still haven't addressed dropping references created in the
transformed monad back into the underlying one again. And this does seem to
be getting rather complicated and expensive... are you sure it's worth the
candle? I'm quite happy to have references depend on a state identifier myself.