    {-# LANGUAGE
            MultiParamTypeClasses,
            FunctionalDependencies,
            GADTs
      #-}

    -- |This module defines the \"MRef\" abstraction, which is a set of
    --  type-classes for things that behave like 'Control.Concurrent.MVar.MVar's.
    --  See the documentation there for more info.
    --
    --  This interface may be subject to future expansion.  Presently, rather
    --  than providing something like 'Control.Concurrent.MVar.tryTakeMVar',
    --  instances for \"'Data.StateRef.Types.ReadRef' sr m ('Maybe' a)\" are
    --  provided, giving 'Data.StateRef.Types.readReference' the same type
    --  tryTakeMRef would have if it existed.  There is currently nothing like
    --  'Control.Concurrent.MVar.tryPutMVar', though.  Perhaps there should be.
    --  Or, perhaps this is the sort of thing the weird (to me) signature of
    --  'Data.IORef.atomicModifyIORef' is for, and an argument for a similar
    --  signature for 'Data.StateRef.Types.modifyStateRef' or the addition of
    --  a new atomicModifyStateRef function.
    --
    --  I would like to resolve these questions in version 0.3 of this package.
    module Data.MRef.Types where

    data MRef m a where
        MRef :: (TakeMRef sr m a, PutMRef sr m a) => !sr -> MRef m a

    class HasMRef m where
        newMRef :: a -> m (MRef m a)
        newEmptyMRef :: m (MRef m a)

    class Monad m => NewMRef sr m a | sr -> a where
        -- |See 'Control.Concurrent.MVar.newMVar'
        newMReference :: a -> m sr
        -- |See 'Control.Concurrent.MVar.newEmptyMVar'
        newEmptyMReference :: m sr
    class Monad m => TakeMRef sr m a | sr -> a where
        -- |See 'Control.Concurrent.MVar.takeMVar'
        takeMReference :: sr -> m a
    class Monad m => PutMRef sr m a | sr -> a where
        -- |See 'Control.Concurrent.MVar.putMVar'
        putMReference :: sr -> a -> m ()