[Haskell-beginners] explaining effects

Rein Henrichs rein.henrichs at gmail.com
Sat Dec 26 18:53:20 UTC 2015


TL;DR: Evaluation is always pure[1]. Execution isn't, but it wasn't
supposed to be in the first place.

> would it make sense to forget about effects and purity and distinguish
only between IO and non-IO? It should be easy enough to tell IO from
non-IO, no?

There is no need to distinguish between IO and non-IO. Everything is pure,
including IO.

When people talk about effects, they tend to mean something encapsulated
and "hidden" by the implementation of bind and return for a particular
Monad instance; the meaning of "effect" is entirely dependent on this
context. For example, State encapsulates the effect of passing an
accumulating parameter to multiple functions and properly threading the
results. Reader encapsulates additional function parameters that are never
varied. Writer encapsulates writing to a "log" (any monoidal accumulator).
The list monad encapsulates the effect of non-determinism (functions that
can return more than one result), allowing you to work with placeholder
variables that represent all possible results at that stage of the
computation. ST encapsulates mutation in way that is *externally
unobservable*. And so on. None of these "effects" are impure. They are all
referentially transparent. They do not mutate any external or global state.
They can all be rewritten by inlining the relevant definitions of bind and
return in a way that will make it obvious that no "funny stuff" is
happening.

One important difference between this sort of encapsulation and the kind
that you might find in an OOP language is that this encapsulation is
*perfect*. These abstractions *do not leak*. There is no way for your
program to externally observe any mutation during evaluation of a State
action and the same holds, mutatis mutandis, for all the other monad
instances.

IO is a common source of confusion, but the important distinction here is
the one that Chris already made: *evaluation* of IO actions is pure,
referentially transparent, and causes no effects (side- or otherwise).
Execution of the `main` IO action by the runtime—and by extension the
execution of those other IO actions that may compose it—is obviously not
pure, but no one is expecting *execution* to be pure: if execution were
required to be pure then the program couldn't be run at all, because any
attempt to run it would cause some sort of externally observable effect
(even if it merely heats up the surrounding space a bit).

A commonly used metaphor that may help to understand this is to consider an
IO action to be like a recipe like one might find in a cookbook. If
`getLine` is the recipe for a particular type of cake then it will be the
same recipe every time it is invoked. The actual cake that you produce when
you execute the recipe may differ—more or less, depending on how proficient
you are at baking—but this does not mean that the recipe itself has changed
each time. And so it is with IO: The actions are pure. They are the same
every time. The results that they produce when executed may change, but
this is not at odds with our claim that the values themselves are pure.

> also, could we say that a function that returns a value of such a type of
which no part is a function (for lack of a better definition) is definitely
a pure function

Yes, and all the other functions are pure too.

[1] Modulo usages of `unsafePerformIO` and friends, but these can and
should be dealt with separately.

On Sat, Dec 26, 2015 at 4:09 AM Imants Cekusins <imantc at gmail.com> wrote:

> for some practical purposes, would it make sense to forget about
> effects and purity and distinguish only between IO and non-IO? It
> should be easy enough to tell IO from non-IO, no?
>
> also, could we say that a function that returns a value of such a type
> of which no part is a function (for lack of a better definition) is
> definitely a pure function
>
> ?
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20151226/5f188506/attachment-0001.html>


More information about the Beginners mailing list