
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