[Haskell-cafe] Monads aren't evil? I think they are.
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
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
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.
The philosophy of Haskell is that searching for purely functional
solution is well worth it.
More information about the Haskell-Cafe