Typesafe MRef with a regular monad

Ashley Yakeley ashley@semantic.org
Wed, 04 Jun 2003 15:19:53 -0700


In article <200306042005.h54K5mG0014203@adric.fnmoc.navy.mil>,
 oleg@pobox.com wrote:

> Ashley Yakeley wrote:
> ] ] Is it possible to actually implement a working instance of RefMonad in 
> ] ] Haskell, without making use of a built-in monad like IO or ST?  
> 
> ] You certainly wouldn't be able to do this for any monad M which had:
> 
> ]   performM :: forall a. M a -> a;
> 
> ] ...because it wouldn't be type-safe: you'd be able to construct coerce 
> ] :: a -> b just as you can with unsafePerformIO.
>  
> Fortunately, that doesn't seem to be the case.

That's only because you've failed to do the difficult part: implement 
newRef. Your monadic solution has a statically typed/sized store: I'd 
say it doesn't properly count as a "heap" since you can't heap new stuff 
on it.

The original problem was to create an instance of 

  class Monad m => RefMonad m r | m -> r where
     newRef :: a -> m (r a)
     readRef :: r a -> m a
     writeRef :: r a -> a -> m ()

without making use of IO or ST. Given some M and R that have

  instance RefMonad M R
  performM :: forall a. M a -> a

one can write this:

  coerce :: forall a b. a -> b;
  coerce a = let
    {
    ref = performM (newRef Nothing);
    } in performM (do
    {
    writeRef ref (Just a);
    mb <- readRef ref;
    case mb of {Just b -> return b;};
    });

-- 
Ashley Yakeley, Seattle WA