[Haskell-cafe] Re: Monads aren't evil? I think they are.

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Tue Jan 13 19:54:44 EST 2009


On Tue, 2009-01-13 at 19:19 -0500, Dan Doel wrote:
> On Tuesday 13 January 2009 5:51:09 pm Luke Palmer wrote:
> > On Tue, Jan 13, 2009 at 11:21 AM, Tim Newsham <newsham at lava.net> wrote:
> > > I have seen several libraries where all functions of a monad have the
> > >
> > >> monadic result (), e.g. Binary.Put and other writing functions. This is
> > >> a clear indicator, that the Monad instance is artificial and was only
> > >> chosen because of the 'do' notation.
> > >
> > > Maybe that was the initial reason, but I've actually found the
> > > Binary.Put.PutM (where Put = PutM ()) to be useful.  Sometimes
> > > your putter does need to propogate a result...
> >
> > But that's the whole point of Writer!  Take a monoid, make it into a monad.
> > Put as a monad is silly.
> 
> You mean it should be Writer instead?
> 
> When GHC starts optimizing (Writer Builder) as well as it optimizes PutM, then 
> that will be a cogent argument.

In that case it's a cogent argument now. :-)

You may be interested to note that PutM really is implemented as a
writer monad over the Builder monoid:

-- | The PutM type. A Writer monad over the efficient Builder monoid.
newtype PutM a = Put { unPut :: PairS a }
data PairS a = PairS a {-# UNPACK #-}!Builder

-- | Put merely lifts Builder into a Writer monad, applied to ().
type Put = PutM ()


> Until then, one might argue that it misses "the whole point of Put".


Back when we were first writing the binary library, Ross converted our
original Put to be a monoid called Builder with Put left as a Writer.
GHC optimises it perfectly, we checked.

The reason we provide Put as well as Builder is purely for symmetry with
code written using Get. Also `mappend` is not so pretty. Another
argument for redefining (++) == mappend :-)

Get doesn't need to be a Monad either, it only needs to be an
applicative functor. Indeed the rules to eliminate adjacent bounds
checks only fire if it is used in this way (using >> also works).

Duncan



More information about the Haskell-Cafe mailing list