[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