[Haskell-cafe] Why do I have to specify (Monad m) here again?

Matthew Brecknell haskell at brecknell.org
Sun Feb 18 12:17:35 EST 2007


Marc Weber said:
> I'll try to explain why I don't get it yet
> 
> 	class (Monad m) => GetMV m a where (1)
> 
> tells that the first param called 'm' is an instance of class m, right?
> Then it doesn't matter wether I use
> 	instance GetMV m          c where 
> or
> 	instance GetMV <any name> c where
> 
> If the class sepecification (1) forces m to be a monad, <any name> has to
> be
> one, too(?)

Let's look at this from another angle: What are you achieving with your
class/instance definitions that you couldn't achieve with a simple
function?

I'm not sure what methods you have, so I'll use the following for the
purpose of discussion. I'm reverting to a single-parameter type class,
since the multi-parameter type class might be clouding the issue:

> class Monad m => MonadFoo m where
>   foo :: m Int
> 
> instance Monad m => MonadFoo m where
>   foo = return 42

How is the above different from just writing the following?

> foo' = return 42

Well, they do have slightly different types:

> foo :: MonadFoo m => m Int
> foo' :: Monad m => m Int

But practically speaking, the MonadFoo class is no different to the
Monad class. For a start, every member of the Monad class is also a
member of the MonadFoo class, according to the sole instance
declaration. Further, you can't define any other instance of MonadFoo,
because it would conflict with the above instance. You're stuck with a
single instance, which means you don't gain anything over the standalone
function.

My point is that the case you're trying to save a few keystrokes on is
not really that useful. Indeed, the point of classes and instances is to
allow different types to inhabit the same class with different
implementations, and to allow other types to not inhabit the class at
all.

Contexts on instance declarations allow you to write an instance which
covers a range of types, but usually the range of types is a proper
subset of the class. It would be rare (if ever) that you would write an
instance declaration covering the entire class, as I've done above.
(Actually, you might do this if you start using overlapping and
undecidable instances, but that's over my head).

I suggest you look through the base libraries to see how contexts on
instance declarations are used in practice.

> When using your example (Monad IO):
> 	class (Monad m) => MonadIO m where
> 		liftIO :: IO a -> m a
> it it basically the same, isn't it?  This declaration forces m to be
> monad..
> which would't hurt if GHC would infer m beeing a monad automatically?

And here's a concrete example. The class definition requires that m be a
Monad before it can be a MonadIO, but here's the important bit: not
every Monad will be a MonadIO. So you would not want an instance
declaration that makes that assumption.




More information about the Haskell-Cafe mailing list