
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.