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