MonadError and fundeps
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
> Also MonadReader and MonadWriter can't have such generic instances anyway
> because their methods have values of type 'm a' as arguments.
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?