Reference types

Ashley Yakeley ashley@semantic.org
Wed, 6 Feb 2002 15:35:05 -0800


At 2002-02-06 03:38, John Hughes wrote:

>Well, I'm still not convinced. A reference *value* can't have the type
>
>      (LiftedMonad (ST s) m) => Ref m a

Oh, yeah, you're right. I made a mistake here:

     newSTRef :: a -> Ref (ST s) a;
	     
	    newSTLiftedRef :: (LiftedMonad (ST s) m) => a -> Ref m a;

This should of course be:

     newSTRef :: a -> (ST s) (Ref (ST s) a);
	     
	    newSTLiftedRef :: (LiftedMonad (ST s) m) => a -> m (Ref m a);

...which won't help, because the Ref will only work in the monad that 
created it. But 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.

>Are you really in Seattle? If so, you must be a real nightbird or a
>tremendously early riser!

Um, yeah, that's a side effect of unemployment, along with haemorrhaging 
open-source software (see Truth). Does anyone need a Haskell developer in 
the greater Seattle area?

-- 
Ashley Yakeley, Seattle WA