
Hi Michael, On Sun, Nov 01, 2009 at 07:15:17AM -0800, Michael Mossey wrote:
I'm trying to understand multi-param typeclasses; a particular one (MonadError); and functional dependencies.
For example, throwError in in the MonadError class definition:
class Monad m => MonadError e m | m -> e where throwError :: e -> m a
In a sense, there is no single type that is an instance of MonadError.
Is this the right way to put it?
I think a better way to put it is that an instance of MonadError is a PAIR of types, instead of a single type.
Error e => MonadError e (Either e)
The code doesn't give the definition, but I suppose it would be:
throwError e = Left e ???
Right. (No pun intended ;)
Now I'm interested in understanding this functional dependency between m and e. For the compiler to decide that a particular instance's definition of throwError is available, it must decide that
e is of class Error (it is given by class constraint) m is a Monad (Either e is such) and then this m -> e thing: I don't know how to put this into words
The m -> e thing isn't a constraint that needs to be satisfied; it gives some extra information to help the compiler with inferring which instance to use. In particular, "m -> e" says "the type chosen for m DETERMINES the type chosen for e"; put another way, "there cannot be two instances with the same type for m but different types for e". So in this case you could not also make an instance MonadError String (Either e). -Brent