There has been a scurry of reaction on twitter and reddit to Robert Fischer’s post saying that Scala is Not a Functional Programming Language. James Iry responded by saying that analogous reasoning leads to the conclusion that Erlang is Not Functional
My first inclination was to suggest that Haskell, as commonly practiced (with monadic IO), is not a functional language either. Instead, I’m going to explain how it is that the C language is purely functional.
The story of C
First, let me make that claim more precise. What I really mean is that almost everyone who “writes C programs” is really programming in a purely functional language. Modulo some minor historical accidents.
“C programmers” really program not in C, but in the purely functional language cpp (the “C Preprocessor”).
As with any purely functional language, cpp consists only of (nestable) expressions, not statements.
Now here’s the clever part: when evaluated (not executed), a cpp expression yields a (pure) value of type
C, which is an ADT (abstract data type) that represents imperative programs.
That value of type
C is then executed (not evaluated) by the cpp language’s RTS (run-time system).
As a clever optimization, cpp’s RTS actually includes a code generator, considerably improving performance over more naïve implementations of the
C abstract data type.
(So now you can see that, “C programmer” is almost always a misnomer when applied to a person.
Instead people are cpp programmers, and cpp programs are the real C programmers (producers of
I don’t think I can buck this misnomer, so I’ll stay with the herd and use “C programming” to mean cpp programming.)
In this way, the geniuses Brian Kernighan and Dennis Ritchie applied monads (from category theory) to programming language design considerably before the work of Moggi and Wadler. (Even earlier examples of this idea can be found, so I’m taking liberty with history, choosing to give K&R credit for the sake of this post.)
Now along the way, some mistakes were made that tarnished the theoretical beauty of cpp+C:
Although cpp is in spirit purely functional, pragmatists insisted on the unnecessary and theoretically awkward construct
#undef, which allows a single name to be re-defined.
Scoping rules are not as clean as, say, the lambda calculus or Scheme, (But hey — even John McCarthy got scoping wrong.)
CADT is implemented simply as
char *, for you type theorists, using a notation from Kleene), and the representation is exposed rather than hidden, so that cpp programs operate directly on strings. The wisdom of data abstraction caught on later.
Fortunately for purists, the relatively obscure programming language Haskell restored the original untarnished beauty of K&R’s vision by fixing these defects.
The type system was modernized, scoping rules improved, and the
C type (renamed to “
IO“, to avoid expensive legal battles) made abstract.
(Admittedly, Haskell also had some shameful pre-teen influences from hooligans like Church, Curry, Landin, and Milner, before it settled into its true cpp+C nature, under the guiding influence of Wadler (under the influence of Moggi).)
What about Haskell?
Which leads to the question: is Haskell+IO a purely functional programming language?
Sure it is, even as much as its predecessor C (more precisely, cpp+C).
Some who ought to know better would claim that Haskell+IO is only technically pure. (See claims and follow-up discussion, in response to a remark from James Iry.)
I must then respond that, in that case, even C programming is only technically pure.
Which is absurd.