[Haskell-cafe] On the purity of Haskell

Chris Smith cdsmith at gmail.com
Fri Dec 30 02:37:05 CET 2011


On Fri, 2011-12-30 at 00:44 +0000, Steve Horne wrote:
> So, to resurrect an example from earlier...
> 
> f :: Int -> IO Int
> f = getAnIntFromTheUser >>= \i -> return (i+1)

Did you mean  f :: IO Int ?  If not, then I perhaps don't understand
your example, and your monad is not IO.  I'll continue assuming the
former.

> Are you claiming that the expression (i+1) is evaluated without knowing 
> the value of i?

I'm not sure what you mean by "evaluated" here.  I'd say it's in normal
form, but it has free variables so it's not even meaningful by itself;
it doesn't have a value in the first place.  On the other hand, the
larger expression, \i -> return (i+1), is closed *and* effectively in
normal form, so yes, I'd definitely say it is evaluated so far as that
word has any meaning at all.

> If not, at run-time your Haskell evaluates those expressions that 
> couldn't be fully evaluated at compile-time.

I certainly agree that the GHC runtime system, and any other Haskell
implementation's runtime system as well, evaluates expressions (some
representation of them anyway), and does lots of destructive updates to
boot.  This isn't at issue.  What is at issue is whether to shoehorn
those effects into the language semantics as a side-effect of evaluation
(or equivalently, force evaluation of expressions to be seen as an
effect -- when you only allow for one of these concepts, it's a silly
semantic game as to which name you call it by), or to treat effects as
semantically first-class concepts in their own right, different from the
simplification of expressions into values.

> If you do, we're back to my original model. The value returned by main 
> at compile-time is an AST-like structure wrapped in an IO monad 
> instance.

Here you're introducing implementation detail here that's rather
irrelevant to the semantics of the language.  Who knows whether compiler
and the runtime implementation build data structures corresponding to an
AST and run a reduction system on them, or use some other mechanism.
One could build implementations that do it many different ways.  In
fact, what most will do is generate machine code that directly performs
the desired effects and use closures with pointers to the generated
machine code.  But that's all beside the point.  If you need to know how
your compiler is implemented to answer questions about language
semantics, you've failed already.

Purity isn't about the RTS implementation, which is of course plenty
effectful and involves lots of destructive updates.  It's about the
language semantics.

-- 
Chris Smith




More information about the Haskell-Cafe mailing list