Reference types

John Hughes rjmh@cs.chalmers.se
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.

John