Reference types

Ashley Yakeley ashley@semantic.org
Tue, 5 Feb 2002 16:54:33 -0800


At 2002-02-05 15:10, John Hughes wrote:

>Oh no, please don't do this! I use the RefMonad class, but *without* the
>dependency r -> m. Why not? Because I want to manipulate (for example) STRefs
>in monads built on top of the ST monad via monad transformers. So I use the
>same reference type with *many different* monads! Your change would make this
>impossible.

I don't think so. Provided you have a class that represents your monads, 
I don't see why you can't do this:

    class (Monad m) => MyMonad m where
        ...

    myIntRef :: (MyMonad m) => Ref m Int;


...except that with Simon's suggested change you wouldn't be able to 
define your own Refs. I believe the best solution to the problem involves 
leaving the existing functions as is but adding something like this:

    data Ref m a = MkRef
        {
        get :: m a,
        set :: a -> m (),
        modify :: (a -> a) -> m ()
        };

    mkRef g s = MkRef g s (\map -> do
        {
        val <- g;
        s (map val);
        });
    
    refBind :: (Monad m) => (m a) -> (a -> Ref m b) -> Ref m b;
    refBind ma arb = MkRef
        (           ma >>= (\a -> get       (arb a)     ))
        (\b ->      ma >>= (\a -> set       (arb a) b   ))
        (\map ->    ma >>= (\a -> modify    (arb a) map ));
    
    class (Monad m) => RefMonad m where
        {
        newRef   :: a -> m (Ref m a);    -- "standard" ref for this monad
        };      
    
    instance RefMonad IO where
        {
        newRef a = do
            {
            r <- newIORef a;
            return MkRef (readIORef r) (writeIORef r) (modifyIORef r)
            };
        };
    
    instance RefMonad (ST s) where
        etc.

The point is that the m -> r dependency is also unnecessary, except when 
you want a new "standard" ref for a monad.

-- 
Ashley Yakeley, Seattle WA