
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@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