4 ms·
This is a fair reflection on one of the biggest barriers to newbs learning Haskell (which I've tried to do a couple of times and failed, in part because the syn
by tjradcliffe 12y ago
This is a fair reflection on one of the biggest barriers to newbs learning Haskell (which I've tried to do a couple of times and failed, in part because the syntax is weird and poorly explained, in part because the tutorials suck, and mostly because I'm not very smart, or so I'm told.)
The Haskell newb gets told two things very early on:
1) Haskell is pure pure pure!
2) Haskell can do IO via monads!
These statements are contradictory. Haskell is either pure, or can do IO (via monads or anything else.) No pure language can do IO. Period. End of story. Any claim to the contrary is simply, utterly, completely false. I don't care how much you wish it was true, or think it's possible to finesse the issue. You can't. And the worst thing you can possibly do is introduce a newb to the new language via a contradiction.
It's like idiots who introduce "negative resistance" with the up-front claim that a device has "negative resistance" without first introducing the generalized concept of resistance that the notion of "negative generalized resistance" depends on. Ordinary, unqualified "resistance" means V/I, not dV/dI, and if you use the unqualified term "resistance" in any other way you are deliberately and with malice aforethought creating confusion. Same goes for "negative temperature", doubled.
Want to teach Haskell? Start like this: "Haskell is an effectively pure language that hides side-effects behind opaque interfaces that return new objects that represent the modified state of the world, rather than old objects that have been modified. This trickery lets us reason about Haskell code in most cases as if it was pure even though it is not."
Claiming purity where there is none is terrible pedagogy. The newb will be confused and have a much harder time getting their head around the language. They will realize that the insiders are working in a different conceptual universe than they are, but won't see any way into that universe and will rightly assume that the insiders are being deliberately obtuse for the sole purpose of excluding newbs.
I am, as stated above, extremely stupid. As such, I am pretty ordinary in this regard. If you want people to learn the damned language, you have to cater to stupid people like me. So discard, play-down, reject and ignore the myth of purity, because that's what it is. A myth. Haskell is not pure. In a pure language the return value of a function depends only on its arguments, but any function that does IO can return any value whatsoever, regardless of what its arguments might be.
I'm sure Haskell purists will respond to this insisting that no, Haskell is really, truly, purely pure... for a certain definition of "purity". It isn't. Monads are a hack to cover necessary impurities. They are a good hack, but to redefine "pure" in such a way that accommodates monads--and this is what you have to do--is just like redefining "resistance" to accommodate "negative resistance". It's perfectly reasonable to generalize the definition of common terms, and perfectly confusing to use the generalization to imply that you mean "just perfectly ordinary resistance" when talking about "negative resistance," or "just perfectly ordinary purity" when talking about "purity with side effects hidden behind monads."
There is no particular value, use or virtue in claiming Haskell is "a truly pure functional language". Claiming the language is "effectively pure for most practical purposes, so you get the provability of pure functional programming by hiding side effects behind monads" seems far more useful. Why the Haskell community is so wedded to the myth of purity--and therefore so insistent about putting monads front and center, as the article rightly decries--is not clear. But the language and the community would be better for putting the myth and the monads behind them.
- tel 12y agoTo go ahead and be that Haskell purist... in normal Haskell code there are no functions which execute side effects in the process of computing their results. Even a function like putStrLn :: String -> IO () merely produces an IO value. It is only when such a value is sequenced into something presented to the RTS as `main` that the effects are realized. This seems like pedantry, but it allows you to construct and compose IO values in many ways (besides just sequentially evaluating them). This ends up giving you "macro like" powers.
- tjradcliffe 12y agoThanks for this answer. I think it points clearly to the source of confusion. To be pedantic back at you, I'm pretty sure your explanation translates to: "So long as you never run a program, Haskell is a pure language." Pedantically speaking, you can't have it both ways. Either the "Haskell" of the claim "Haskell is pure" includes the RTS or it does not. If it does, it is not pure but can run programs. If it does not, it is pure but cannot run programs. A programming language that you can't run programs in is not very useful or interesting, so I'd really think it was a better move to define "Haskell" in such a way that programs can be run, and accept that under that definition Haskell is impure, although it retains a kind of effectively pure formalism that allows provability and such, which is awesome. Either way, it is really important to emphasize in any description of the language that "At runtime Haskell is not pure". Otherwise newbs like me will simply be confused by the contradiction between the claim "Haskell [considered as an unexecutable language] is pure" and "Haskell [considered as a set of instructions to the RTS] is capable of doing IO". The two completely different meanings of "Haskell" must be made clear if profound confusion is to be avoided.
- codygman 12y agoI think we can agree the construction of the actions as pure. I'm not sure about after those actions are realized in main.
- tel 12y agoEh, I don't care much about names. Purity-up-until-RTS being taken seriously makes it easy to think of computations both pure and impure. I get to choose whether to interpret IO as an imperative, impure language subset of Haskell or as a pure type. Both have their advantages. If your language is impure then you usually can only choose the former.