Reference types
John Hughes
rjmh@cs.chalmers.se
Wed, 6 Feb 2002 12:38:50 +0100 (MET)
Ashley Yakeley wrote:
At 2002-02-06 01:09, John Hughes wrote:
>No no no! This still makes the reference type depend on the monad type, which
>means that I cannot manipulate the same reference in two different monads!
Yes you can. Consider:
-- 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 -> Ref (ST s) a;
newSTLiftedRef :: (LiftedMonad (ST s) m) => a -> Ref m a;
newSTLiftedRef = liftRef . newSTRef;
With me so far? Now here's the clever bit: Refs created with
newSTLiftedRef are of type '(LiftedMonad (ST s) m) => Ref m a'. This
means they will work equally well as 'Ref (ST s) a' as they will as 'Ref
TransformedMonad a'.
Well, I'm still not convinced. A reference *value* can't have the type
(LiftedMonad (ST s) m) => Ref m a
This is the type of a function, which given a dictionary returns a reference.
Moreover, since when I write
do r <- newSTLiftedRef x
...
then I am effectively lambda-binding r, then r cannot have this type. It can only
have an instance of it ... which ties r to the monad m.
Am I missing something here? Seems to me, to do what you're suggesting I
would have to put the context inside the Ref type itself:
data Ref s a = Ref
{ readRef :: forall m. LiftedMonad (ST s) m => m a,
writeRef :: forall m. LiftedMonad (ST s) m => a -> m () }
But now the s had to go back in the type of the reference...
Are you really in Seattle? If so, you must be a real nightbird or a
tremendously early riser!
John