Dne 06/03/2013 09:11 PM, Henning Thielemann napsal(a):


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.

For monads, it's (AFAIK) always this way, because m is always in the result, but not necessarily the other type. Let's consider

readRef :: r a -> m a

In order to type-check x in readRef x, we need to determine r a from m a, so the dependency must be m -> r.