# MonadError and fundeps

**Lauri Alanko
**
la@iki.fi

*Fri, 11 May 2001 15:45:00 +0300*

On Fri, May 11, 2001 at 02:14:24PM +0200, Marcin 'Qrczak' Kowalczyk wrote:
>* On Fri, 11 May 2001, Lauri Alanko wrote:
*>*
*>* > Why? This makes composing and "subtyping" impossible:
*>* >
*>* > instance (MonadTrans t, MonadState s m, Monad (t m))
*>* > => MonadState s (t m) where
*>* > get = lift get
*>* > put = lift . put
*>*
*>* This instance is illegal anyway. One of types in the instance head must be
*>* a type constructor applied to something (type variables in Haskell 98,
*>* anything with -fglasgow-exts).
*
Ah. So it seems. Pardon. It works in Hugs, though.
>* Even if it was legal, it would overlap with
*>* instance Monad m => MonadState s (StateT s m)
*
Yep, but in hugs +o the latter overrides the first one. Which is quite
convenient.
>* Also MonadReader and MonadWriter can't have such generic instances anyway
*>* because their methods have values of type 'm a' as arguments.
*
Oh?
translift :: (MonadTrans t, Monad m, Monad (t m))
=> (m a -> m b) -> t m a -> t m b
translift f m = m >>= lift . f . return
instance (MonadTrans t, MonadReader r m, Monad (t m))
=> MonadReader r (t m) where
ask = lift ask
local = translift . local
instance (MonadTrans t, MonadWriter w m, Monad (t m), Monoid w) =>
MonadWriter w (t m) where
tell = lift . tell
listen = translift listen
pass = translift pass
>* OTOH without the fundep there are ambiguities. For example:
*>*
*>* class ParsingState s where
*>* stateInput :: s -> String
*>* stateSkip :: Int -> s -> s
*>*
*>* instance ParsingState String where ...
*>* instance ParsingState s => ParsingState (s, Pos) where ...
*>*
*>* input :: (ParsingState s, MonadState s m) => m String
*>* -- Ambiguous without the fundep.
*>* input = gets stateInput
*
So it is, and why not? Is it inconceivable that m might actually have
multiple ParsingStates, and thus you really have to specify which one you
want to use to get the input?
Lauri Alanko
la@iki.fi