That was the last variant I mentioned in that post.

The complication that introduces is that you then can't auto-lift newRef, etc. into transformer stacks.

-Edward


On Mon, Jun 3, 2013 at 3:11 PM, Henning Thielemann <lemming@henning-thielemann.de> wrote:

On Mon, 3 Jun 2013, Edward Kmett wrote:

The first option is

class Monad m => MonadRef r m | m -> r where
  newRef :: a -> m (r a)
  ...

This has the benefit of using quite portable extensions.

The second option is

class Monad m => MonadRef m where  type Ref m :: * -> *
  newRef :: a -> m (Ref m a)
 
This takes us into GHC specific territory, by using type families, but avoids polluting every type that uses
one with an extra 'ref' param. I use this variant in my as-yet-unreleased 'revisions' package.

Both of these have the benefit that they can work with transformers, but they carry the limitation that you
can't have multiple reference types for the same monad. e.g. you can't use the same combinators for both
IORefs and, say, MVars or TVars within the same monad. This is arguably not so much a problem as they have
very different operational semantics!

I thought the functional dependency should be the other way round: From the reference type to the monad where it lives in.