
At Thu, 10 Dec 2009 12:07:32 +0000, Magnus Therning wrote:
As I understand it it all started with laziness. I don't know if laziness is impossible without purity
More or less. Haskell is a language where anything can be evaluated lazily by default. Unlike say Scheme, where if you want something to be evaluated lazily you have to be explicit about it, in Haskell it's the opposite - if you want something to be evaluated _strictly_ you have to be explicit about it. If you write an impure expression in Haskell (e.g. using unsafePerformIO) the side-effects of it might be executed once, twice, or never, depending on the Haskell implementation in use, the optimisation flags, or even other Haskell code in the system. And the side-effects might be executed at unpredictable times, in an unpredictable order, and only some of them might occur. Now, this might be fine for debugging purposes, where you want to see what is being done under the hood - but for most other side-effects, you really want them to occur in a more controllable way. Hence, to answer John's question, a lazy language _has_ to be pure (apart from the unsafe functions) because laziness (or, to be more technically correct, non-strict evaluation) is incompatible with good control of the side-effects arising from impure code. Both Clean and Haskell deal with side-effects by allowing the programmer to write imperative code in a pure way - in Haskell, by using monads or FRP, and in Clean by using world-passing and uniqueness types. Now, that answer probably suffices for a Haskell beginner. Of course eventually you realise time and space usage is a side-effect, and _that_ needs to be controlled as well... but despite this, I think my answer is basically right. However, that's not the _only_ reason why you might want purity. Even in a strict language, purity makes it easier to reason about code, because you don't have to consider the environment, only the parameters that are passed in. Of course, it gets more complicated with monads, because the Environment monad and the IO monad both give you implicit environments at the level of "running the monadic actions". But even then, it's supposed to be easier to reason about (once you get the hang of it), and I'd broadly agree with this. -- Robin