
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.