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

Alberto G. Corona agocorona at gmail.com
Wed Jan 14 12:22:12 EST 2009

The question of imperative versus pure declarative coding has brought to my
mind some may be off-topic speculations.  (so please don´t read it if you
have no time to waste):  I´m interested in the misterious relation bentween
mathematics, algoritms and reality (see
this<http://arxiv.org/pdf/0704.0646>for example).  Functional
programming is declarative, you can model the
entire world functionally with no concern for the order of calculations. The
world is mathematical. The laws of physics have no concern for sequencing.
But CPUs and communications are basically sequential.  Life is sequential,
and programs run along the time coordinate. Whenever you have to run a
program,  you or your compiler must sequence it.  The sequentiation  must be
done by you or your compiler or both. The functional declarative code can be
sequenced on-the-run by the compiler in the CPU by the runtime. but IO is
You have to create, explicitly or implicitly the sequence of IO actions
because the external events in the external world  are not controlled by you
or the compiler. So you, the programmer are the responsible of sequencing
effects in coordination with the external world. so every language must give
you ways to express  sequencing of actions. that is why, to interact with
the external world you must think in terms of algorithms, that is ,
imperatively, no matter if you make the imperative-sequence  (relatively)
explicit with monads or if you make it trough pairs (state, value) or
unsafePerformIO or whatever. You have to think imperatively either way,
because yo HAVE TO construct a sequence. I think that the elegant option is
to recognize this different algorithmic nature of IO by using the IO monad.
In other terms, the appearance of input-output in a problem means that you
modelize just a part of the whole system. the interaction with the part of
the system that the program do not control appears as input output. if the
program includes the model of the environment that give the input output
(including perhaps a model of yourself), then, all the code may be side
effects free and unobservable. Thus, input output is a measure of the lack
of  a priori information.  Because this information is given and demanded at
precide points in the time dimension with a quantitative (real time) or
ordered (sequential) measure, then these impure considerations must be taken
into account in the program. However, the above is nonsensical, because if
you know everithing a priory, then you don´t have a problem, so you don´t
need a program. Because problem solving is to cope with unknow data that
appears AFTER the program has been created, in oder to produce output at the
corrrect time, then the program must have timing on it. has an algoritmic
nature, is not pure mathemathical. This applies indeed to all living beings,
that respond to the environment, and this creates the notion of time.

Concerning monadic code with no side effects, In mathematical terms,
 sequenced (monadic) code are mathematically different from declarative
code: A  function describes what in mathematics is called a  "manifold" with
a number of dimensions equal to the number of parameters.  In the other
side, a sequence describe a particular  trayectory in a manifold, a ordered
set of points in a wider manyfold surface. For this reason the latter must
be described algorithmically. The former can be said that include all
possible trajectories, and can be expressed declaratively. The latter is a
sequence  . You can use the former to construct the later, but you must
express the sequence because you are defining the concrete trajectory in the
general manifold that solve your concrete problem, not other infinite sets
of related problems. This essentially applies also to IO.

 Well this does not imply that you must use monads for it. For example, a
way to express a sequence is a list where each element is a function of the
previous.  The complier is forced to sequence it in the way you whant, but
this happens also with monad evaluation.

This can be exemplified with the laws of Newton: they are declarative. Like
any phisical formula. has no concern for sequencing. But when you need to
simulate the behaviour of a ballistic weapon, you must use a sequence of
instructions( that include the l newton laws). (well, in this case the
trajectory is continuous integrable and can be expressed in a single
function. In this case, the manifold includes a unique trajectory, but  this
is not the case in ordinary discrete problems,) . So any language need
declarative as well as imperative elements to program mathematical models as
well as algorithms.


2009/1/11 Apfelmus, Heinrich <apfelmus at quantentunnel.de>

> 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
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090114/71fc060f/attachment.htm

More information about the Haskell-Cafe mailing list