[Haskell-cafe] IO is a bad example for Monads [was: do]

Ben Franksen ben.franksen at online.de
Mon Dec 3 21:36:19 EST 2007

Dan Piponi wrote:
> On Dec 3, 2007 3:54 PM, Ben Franksen <ben.franksen at online.de> wrote:
>> I don't buy this. As has been noted by others before, IO is a very
>> special case, in that it can't be defined in Haskell itself, and there is
>> no evaluation function runIO :: IO a -> a.
> I'm not sure what a function of type m a -> a has to do with the
> concept of a monad. And I don't really see what the problem is with 
> the IO monad not being definable in (pure) Haskell. 

Funny you say that because this is exactly my point! Both have nothing to do
with monads per se.

But if IO is not only the first monad one learns about, but also used as the
first example to explain monads in general, then the special features of IO
will remain associated with monads in general, leading to a whole jumble of
completely wrong ideas about them.

For example, since IO can't be defined in Haskell, Monads get associated
with the idea that there is some 'magic' to make them work going on. (The
OP's question about 'the do construct' nicely illustrates this.)

Another common fallacy is to think of monads as 'sequencing effects', when
in fact this is not necessarily the case. Again, IO is a bad example,
because it is too special to generalize from, its effect base too complex
to study comprehensively, and its implementation not accessible and
therefore obscure. With a simple monad it is easy to see that, if any
sequencing of effects happens at all, then this is due to data dependencies
alone, period.

(I fell afoul of both of the above mistakes and it wasn't easy to get them
out of my head.)

> IO exposes the 
> same interface as every other Monad, and you need to use that
> interface to get visible results. So people have to learn it whatever.
> And the whole point of the Monad is that it's an interface, not a
> specific implementation.

Indeed, it is an interface, and a /very/ general one. It is in fact so
general that in itself alone it is completely useless. You always need an
effect base to get useful things done.

This is yet another problem with IO as the standard example for monads: its
effect base is huge and poorly structured. This again makes it difficult to
see exactly which intuitions about IO can be generalized to arbitrary
monads and which not.

People (and especially those who start learning Haskell, coming form
imperative languages) keep asking the question: all very nice, but what
exactly /is/ a monad? As with the concept of a group in algebra ('a set
with an operation bla bla satisfying the laws ...)', you can of course
say 'a type constructor of kind bla bla with functions bla bla satisfying
the laws...'. However this won't really help the newcomer. What helps is
examples. And looking into the implementation of a simple monad greatly
helps to dispell many kinds of wrong ideas one might have (due to exclusive
exposure to IO as the prime example for a Monad).

>> I'd rather use a simple example like Maybe (modeling failure as an
>> effect).
> And I'd like to see more people getting off the ground doing
> interesting stuff with Haskell before their attention spans for
> pointless-seeming new stuff run out. I'm not talking about the
> smartest people in computer science courses here. I'm talking about
> the millions of people writing everyday Python and Ruby scripts, say,
> who might benefit from a more expressive, type-safe, well-thought out,
> fast and compiled language.

What is pointless about failure and how to handle it? IMO this is the /most/
immediate practical problem one encounters whenever the Python or Ruby (or,
for that matter, Haskell) script starts to exceed a few lines.


More information about the Haskell-Cafe mailing list