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

Apfelmus, Heinrich apfelmus at quantentunnel.de
Sun Jan 11 04:44:40 EST 2009


Ertugrul Soeylemez wrote:
> Let me tell you that usually 90% of my code is
> monadic and there is really nothing wrong with that.  I use especially
> State monads and StateT transformers very often, because they are
> convenient and are just a clean combinator frontend to what you would do
> manually without them:  passing state.

The insistence on avoiding monads by experienced Haskellers, in
particular on avoiding the IO monad, is motivated by the quest for elegance.

The IO and other monads make it easy to fall back to imperative
programming patterns to "get the job done". But do you really need to
pass state around? Or is there a more elegant solution, an abstraction
that makes everything fall into place automatically? Passing state is a
valid implementation tool, but it's not a design principle.


A good example is probably the HGL (Haskell Graphics Library), a small
vector graphics library which once shipped with Hugs. The core is the type

  Graphic

which represents a drawing and whose semantics are roughly

  Graphic = Pixel -> Color

There are primitive graphics like

  empty   :: Graphic
  polygon :: [Point] -> Graphic

and you can combine graphics by laying them on top of each other

  over    :: Graphic -> Graphic -> Graphic

This is an elegant and pure interface for describing graphics.

After having constructed a graphic, you'll also want to draw it on
screen, which can be done with the function

  drawInWindow :: Graphic -> Window -> IO ()

This function is in the IO monad because it has the side-effect of
changing the current window contents. But just because drawing on a
screen involves IO does not mean that using it for describing graphics
is a good idea. However, using IO for *implementing* the graphics type
is fine

  type Graphics = Window -> IO ()

  empty          = \w -> return ()
  polygon (p:ps) = \w -> moveTo p w >> mapM_ (\p -> lineTo p w) ps
  over g1 g2     = \w -> g1 w >> g2 w
  drawInWindow   = id


Consciously excluding monads and restricting the design space to pure
functions is the basic tool of thought for finding such elegant
abstractions. As Paul Hudak said in his message "A regressive view of
support for imperative programming in Haskell"

   In my opinion one of the key principles in the design of Haskell has
   been the insistence on purity. It is arguably what led the Haskell
   designers to "discover" the monadic solution to IO, and is more
   generally what inspired many researchers to "discover" purely
   functional solutions to many seemingly imperative problems.

   http://article.gmane.org/gmane.comp.lang.haskell.cafe/27214

The philosophy of Haskell is that searching for purely functional
solution is well worth it.


Regards,
H. Apfelmus



More information about the Haskell-Cafe mailing list