[Haskell-cafe] Stacking monads

Jonathan Cast jonathanccast at fastmail.fm
Fri Oct 3 16:26:52 EDT 2008


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




More information about the Haskell-Cafe mailing list