| Suppose you want to define an instance of MonadState for another monad like 
| MaybeT.  You would need to write code like this:
|  
|       instance (MonadState s m) => MonadState s (MaybeT m) where
|           get = lift get
|           put = lift . put
|  
|  This code fails the coverage condition, because class argument
|  (MaybeT m) does not contain the type variable s. 

The issue doesn't even arise with type families:

        class MonadState m where
          type State m :: *

        instance MonadState m => MonadState (MaybeT m) where
          type State (MaybeT m) = State m

So examples that fail the coverage condition in fundeps, but (as you argue) are 
ok because the context expresses the dependency, are sometimes just fine with 
type families.

|  Now if, in addition to lifting the coverage condition, you add
|  OverlappingInstances, you can do something even better--you can write
|  one single recursive definition of MonadState that works for all
|  MonadTrans types (along with a base case for StateT).  This is far
|  preferable to the N^2 boilerplate functions currently required by N
|  monad transformers:
|  
|       instance (Monad m) => MonadState s (StateT s m) where
|           get = StateT $ \s -> return (s, s)
|  
|       instance (Monad (t m), MonadTrans t, MonadState s m) =>
|              MonadState s (t m) where
|               get = lift get
|               put = lift . put

Why do you need the first instance?  Isn't the second sufficient for (StateT s 
m) as well?

Simon

_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime

Reply via email to