[Haskell-cafe] Re: what is inverse of mzero and return?

Jorge Adriano Aires jadrian at mat.uc.pt
Sun Jan 23 00:10:28 EST 2005

> >concat (map c (a ++ b)) = concat (map c a) ++ concat (Map c b),
> >
> >which is easily seen to be true (if applying c to an element of a causes
> > an error, neither side will go past that).
> >
> >Daniel
> So do we consider [] to be fail?, Monad.hs defines:

I will ignore "fail" if you don't mind. I can only think of it as a convenient 
hack. I'll get to failure later. If the monad represents a state then IMO 
mplus should be the most intuitive definition for the sum of two such states. 

> instance MonadPlus [] where
>    mzero = []
>    mplus = (++)

On the list monad, I think of the mplus operation as the "union" two 
non-deterministic states. Mzero is the state that works as the identity 
(which is when you have no possible state at all). 

MonadPlus instances for Parsers are similar, p1 mplus p2  is a parser p that 
will return the concatenation of the [(a, string)]  lists that would be 
returned by p1 and p2.

The datatype Maybe,  on the other hand, just allows us to keep at most one 
valid state. Summing "no state" with "some state" gives "some state", if we 
have two states, we get to keep the first.

And all seems fine to me, and I haven't mentioned failure.

> What would happen if this was the definition?
> instance MonadPlus [] where
>    mzero = []
>    mplus a b
>        | a == [] = b
>        | otherwise = a

Then, I'd say you're not thinking of monadic sums, but of catching errors, and 
the appropriate place for that is the class MonadError. 

Such a function can easily be written in terms of catchError. It seems quite 
useful, so it would probably make a good method with default instance:
skipError x y = catchError x (\_->y)

And of course we need MonadError instances for Maybe and Lists.

instance MonadError () Maybe where
      throwError _           = Nothing
      Nothing `catchError` h = h ()
      jx  `catchError` _     = jx

instance MonadError () [] where
      throwError _      = []
      [] `catchError` h = h ()
      xs `catchError` _ = xs

The Maybe datatype is used to model computation errors all the time, so I 
never understood why its MonadError instance was not provided. The List 
instance seems pretty fair too.

And there you have, 
skipError [1,2] [] = [1,2]
skipError [] [1,2] = [1,2]
skipError [1,2] [3,4] = [1,2]


More information about the Haskell-Cafe mailing list