Yet Another Monad Tutorial
Peter G. Hancock
Tue, 12 Aug 2003 18:24:52 +0100
>>>>> Jeff Newbern wrote (on Tue, 12 Aug 2003 at 17:20):
> In the section "No Way Out":
> The IO monad is a familiar example of a one-way monad in Haskell.
> Because you can't escape from the IO monad, it is impossible to write a
> function that does a computation in the IO monad but returns a
> non-monadic value.
I wouldn't say that, as it is inaccurate. Of course you can return a
value of _some_ monadic type eg. (Maybe ...).
> Not only are functions of the type IO a -> a
> impossible to create,
You can quite easily write a function of type IO (IO a) -> IO a, which
is a special case of that type.
> but any function whose result type does not
> contain the IO type constructor is guaranteed not to use the IO monad.
That's rather vague: what does it mean for a function to use a monad?
> Other monads, such as List and Maybe, do allow values out of the monad.
> So it is possible to write non-monadic functions that internally do
> computations in those monads. The one-way nature of the IO monad also
> has consequences when combining monads, a topic that is discussed in
> part III.
In summary, I've only a vague idea of what you are trying to say. If you
can't reformulate it more precisely, don't add the above stuff.
> and a little farther down:
> Some people argue that using monads to introduce non-pure features into
> Haskell disqualifies it from claiming to be a pure functional language.
> This subtle question not particularly relevant to the practical
> programmer is revisited in the context of the I/O monad later in the
That's fair enough. I don't think the question is so much subtle as
religious, as we might expect from the terminology of "purity".
> Later, in the section on the I/O monad:
> In Haskell, the top-level main function must have type IO (), so that
> programs are typically structured at the top level as an
> imperative-style sequence of I/O actions and calls to functional-style
> code. Revisiting the debate about the purity of Haskell (in a functional
> sense), it is important to note that the IO monad only simulates
> imperative-style I/O.
That (about simulation) seems weak. A simulation isn't a vague syntactic
> The functions exported from the IO module do not
> perform I/O themselves. They return I/O actions, which describe an I/O
> operation to be performed. The I/O actions are combined within the IO
> monad (in a purely functional manner) to create more complex I/O
> actions, resulting in the final I/O action that is the main value of the
> program. The result of the Haskell compiler is an executable function
> incorporating the main I/O action. Executing the program "applies" this
> ultimate I/O action to the outside world to produce a new state of the
That seems to me the wrong thing to say. There is no application. Whether
or not the word is put in quotes, it is something involving a function
and an argument. An IO action is not a function.
> This occurs only once per execution of the program, and since the
> state of the world changes for each execution, the issue of purity is
> neatly side-stepped.
By "the program", I think you mean the IO action. I think it is right to
speak of the action as something that is executed. Execution may involve
(side-effect free) calculation; but execution is something essentially
different from calculation, not an impure form of it.
I'm sorry to sound negative -- it's just that you invited criticism.
Your pages seem generally of a very high quality to me. Sorry not
to be more constructive too.