[Haskell-cafe] Re: Can we come out of a monad?

mokus at deepbondi.net mokus at deepbondi.net
Wed Aug 11 09:49:07 EDT 2010


>
> On 11 Aug 2010, at 14:17, Ertugrul Soeylemez wrote:
>>
>> There is a fundamental difference between an IO computation's result and
>> a Haskell function's result.  The IO computation is simply a value, not
>> a function.
>
> That's a rather odd distinction to make – a function is simply a value in
> a functional programming language.  You're simply wrapping up "we're
> talking about haskell functions when we talk about referential
> transparency, not about IO actions" in a way that maintains the warm fuzzy
> feeling.
>
> Bob
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>

I don't know whether anyone is calling the execution of IO actions pure -
I would not, at any rate.  At some level, things MUST 'execute', or why
are we programming at all?  Philosophical points aside, there is still a
meaningful distinction between evaluating and executing a monadic action. 
While execution may not be pure, evaluation always is - and in the
examples given so far in this thread, there is (trivial) evaluation
occurring, which is the pure part that people have been referring to
(while ignoring the impure execution aspect).  Consider a variation on the
random integer theme, where the evaluation stage is made non-trivial. 
Assuming existence of some functions randomElement and greet of suitable
types:

> main = do
>     putStr "What names do you go by (separate them by spaces)? "
>     names <- fmap words getLine
>     greetRandomName names
>
> greetRandomName [] = putStrLn "Hello there!"
> greetRandomName names = randomElement names >>= greet

The result of _evaluating_ "greetRandomName name" is either @putStrLn
"Hello there!"@ or @randomElement names >>= greet@, depending whether the
input list is empty.  This result absolutely can be substituted for the
original expression and potentially further pre-evaluated if "names" is a
known quantity, without changing the meaning of the program.  And, to
address an idea brought up elsewhere in this thread, it is absolutely true
as pointed out before that given the right (monadic) perspective a C
program shares exactly the same properties.

There is real additional purity in Haskell's case though, and it has
absolutely nothing to do with hand-waving about whether IO is pure, "very
pure", extra-super-distilled-mountain-spring-water pure, or anything like
that.  As you rightly point out, executing IO actions at run-time is not
pure at all, and we don't want it to be.  The difference is that while in
Haskell you still have an IO monad that does what C does (if you look at C
in that way), you also have a pure component of the language that can be
(and regularly is, though people often don't realize it) freely mixed with
it.  The monadic exists within the pure and the pure within the monadic. 
'greetRandomName' is a pure function that returns an IO action.  That's
not hand-waving or warm fuzzies, it's fact.  greetRandomName always
returns the same action for the same inputs.  The same distinction is
present in every monad, although in monads that are already pure, such as
Maybe, [], Cont, etc., it's not as big a deal.

The mixture is not as free as some would like; the fact that Haskell has
this distinction between monadic actions and pure values (and the fact
that the former can be manipulated as an instance of the latter) means
that the programmer must specify whether to evaluate ("=") or execute
("<-") an action, which is a source of endless confusion for beginners and
debate over what "pure" means.  I don't expect I'll put an end to either,
but I would like to point out anyway that, if you accept that distinction
(the reality of which is attested by the existence of a computable
function - the type checker - for making the distinction), it's fairly
easy to see that evaluation is always pure, excepting abuse of
unsafePerformIO, et al., and execution is not.  Both occur in the context
of do-notation.  Functions returning monadic actions (whether the
resulting action is being evaluated or executed) are still always
evaluated to yield an action.  That evaluation is pure.  The execution of
the action yielded may not be, nor should it have to be - that's the whole
point of IO!  But we still have as much purity as is actually possible,
because we know exactly where _execution_ occurs and we don't pretend it
doesn't by confusing definition with assignment.  "=" always means "=" in
Haskell, and "<-" doesn't.  In C, "=" always means "<-", even when the RHS
is a simple variable reference (consider "x = x;").

-- James



More information about the Haskell-Cafe mailing list