| main is never pure. Your `procedure` is also not pure (and also not referentially transparent). You can write impure code in Haskell, which your example demonstrates very well. But then it is necessarily IO code. Non-IO code, on the other hand, is always pure (and referentially transparent). > but I don't see that that changes anything It changes everything, but I can't explain it any better than I did above. > So what is it that makes Haskell a pure functional language and Python not? If you give me a Haskell procedure `f1 :: Int -> Int` without showing me the content, I still know that it is referentially transparent and pure. If f1 evaluates x to y once, I know that it ALWAYS evaluates x to y. If a main program in which f1 is used generates a screen output, for example, I can safely exclude f1 as the source of this side effect. If you give me a function `f2 :: Int -> IO Int` instead, I can't draw all these conclusions. In Python, these conclusions would be invalid from the start. Now you can say, “So what? Who cares?” But it helps me enormously when designing and structuring programs, understanding programs, localizing program behavior, etc. If you don't see any added value in this distinction (ensured by the compiler), we don't have to argue about it. But I simply cannot agree with you that this does not represent a conceptual and formally justified difference between Haskell and Python. Of course you can program purely functionally in Python. Just as you can program in a dynamically typed language as if you were dealing with static data types. Or in Java without throwing exceptions and null references around everywhere. Or in C without segmentation faults. These are not normative or moral comparisons, but other examples of the fact that you can of course program in such a way that the code has certain properties, even if the compiler does not secure these properties. The question is whether you want that. |
Ah, it's possible I misunderstood you. I missed that you said "Purely functional languages force you to program this way by default". I mistakenly assumed you were saying that in a purely functional language you can only program purely.
So you are saying that Haskell is a pure functional language, but you can also write non-pure things in it? So being a "pure language" is more a case of what sort of style is encouraged rather than what sort of style is possible?
> (and also not referentially transparent)
Interesting. Could you explain what you mean by that? (The definition of referential transparency that I know doesn't apply to functions but to languages.)
> You can write impure code in Haskell, which your example demonstrates very well. But then it is necessarily IO code. Non-IO code, on the other hand, is always pure (and referentially transparent).
That's interesting. How do you distinguish these two pieces of code:
is the former impure and the latter pure? Or are both impure?> So what is it that makes Haskell a pure functional language and Python not?
If you give me a Haskell procedure `f1 :: Int -> Int` without showing me the content, I still know that it is referentially transparent and pure ... In Python, these conclusions would be invalid from the start.
Do you mean because of the type? If not, I don't understand what distinction you're drawing, and what makes the conclusions invalid for Python. If so, then does a pure language have to be typed? Would it be impossible for a pure language to be untyped?
> Now you can say, “So what? Who cares?” But it helps me enormously when designing and structuring programs, understanding programs, localizing program behavior, etc. If you don't see any added value in this distinction (ensured by the compiler), we don't have to argue about it.
We don't have to argue about it. I program in Haskell every day and reap the benefits :)
> But I simply cannot agree with you that this does not represent a conceptual and formally justified difference between Haskell and Python.
I agree there's a conceptual and formally justified difference between Haskell and Python. I just don't agree with you about how to characterize it :)
To reiterate my characterization, it is that Haskell has "referential transparency", that is
has the same result as regardless of how many times (or zero) x occurs. That's it! Nothing to do with "purity", "IO", "processing arguments", "non-static contexts" or "side effects". Now I may be wrong. That's why I'm trying to understand what you think the characterization is.But so far I have never discovered a benefit of programming "purely" in Haskell that is not ultimately a consequence of what I call "referential transparency" above. Do you know one?