
On Fri, 2008-10-03 at 21:12 +0100, Andrew Coppin wrote:
Brandon S. Allbery KF8NH wrote:
On Oct 3, 2008, at 15:10 , Andrew Coppin wrote:
Again, it looks like MonadPlus == Monad + Monoid, except all the method names are different. Why do we have this confusing duplication?
Because typeclasses aren't like OO classes. Specifically: while you can specify what looks like class inheritance (e.g. "this Monad is also a Monoid" you can't override inherited methods (because it's a Monad, you can't specify as part of the Monad instance the definition of a Monoid class function). So if you want to define MonadPlus to look like a Monad and a Monoid, you have to pick one and *duplicate* the other (without using the same names, since they're already taken by the typeclass you *don't* choose).
I was thinking more, why not just delete MonadPlus completely, and have any function that needs a monad that's also a monoid say so in its context?
This would be clunky. Consider: select as = msum $ do (as0, a:as) <- breaks as return $ do x <- a return (x, as0 ++ as) -- | Divide a list into (snoc-list, cons-list) pairs every possible -- way breaks :: [a] -> [([a], [a])] breaks as = breaks [] as where breaks' as0 [] = [(as0, [])] breaks' as0 (a:as) = (as0, a:as) : breaks' (a:as0) as You can say select :: MonadPlus m => [m a] -> m (a, [m a]) but not select :: (Monad m, Monoid (m a)) => [m a] -> m (a, [m a]) --- for this particular implementation, you need select :: (Monad m, Monoid (m (a, [m a]))) => [m a] -> m (a, [m a]) but then if you want to write select_ = fmap fst . select you have select_ :: (Monad m, Monoid (m (a, [m a]))) => [m a] -> m a . This is a wtf constraint, obviously. You can avoid this by writing select_ :: (Monad m, forall b. Monoid (m b)) => [m a] -> m a but that's somewhat beyond the scope of the existing type class system. Unless you write a new type class that is *explicitly* (Monad m, forall b. Monoid (m b)). Which is what MonadPlus is. jcc