In case someone misses the point of the article -- I know I did, originally! -- the author explicitly lays it out in a comment:
> "Sadly–and here is the real intent behind my post–many Haskell programmers believe that IO is necessary to do “real programming”, and they use Haskell as if it were C (relegating lots of work to IO). In other words, monadic IO has proved to be such a comfortable “solution” to I/O in a functional language, that very few folks are still searching for a genuinely (not merely technically) functional solution. Before monadic IO, there was a lot of vibrant and imaginative work on functional I/O. It hadn’t arrived yet, but was still in touch with the Spirit of functional programming. With the invention and acceptance of monadic imperative programming, it’s like the Haskell community wandered into an opium den and are still lying there in a fog.
> [...]
> "By relating Haskell+IO to cpp+C, I’m not trying to lower the former or elevate the latter. Instead, I’m trying to waken functional programmers out of the opium fog and remind them how fun and creative genuinely functional programming can be."
I love Haskell but I'm not well-versed enough to know why other alternatives to monadic IO were discarded. I do know Haskell predates the IO monad.
This recent paper by Oleg Kiselyov ("Effects Without Monads: Non-determinism Back to the Meta Language" https://arxiv.org/abs/1905.06544https://www.youtube.com/watch?v=fABeIG_HiyU) explores an alternative to monads for structuring effectful computations in OCaml. The effect used in the examples is nondeterminism, instead of IO.
Another functional approach to I/O is "effect systems". I'm not aware of "stable" functional language with them in it though. It's mostly academic at this point.
I don't think it's the io Monad. It's more do-notation sugar. Nobody would use that crazy free variable scoping pattern if it wasn't for that notation.
“Java programmers” really program not in Java, but in a purely functional language called 'cat'. As with any purely functional language, cat consists only of expressions, not statements. Now here’s the clever part: when evaluated (not executed), a cat expression yields a (pure) value of type Java, which is an ADT (abstract data type) that represents imperative programs. That value of type Java is then executed (not evaluated) by the cat language’s RTS (run-time system). As a clever optimization, cat’s RTS actually includes a code generator, considerably improving performance over more naïve implementations of the Java abstract data type.
I wasn't using HN back in 2015 (let alone in 2009) so I'm glad this was re-submitted. It's been more than 4 years which is sufficient time for new users or for people to come back to it with new opinions.
It's interesting to see what people thought 4 or 10 years ago about the same article. Those links aren't to chide the submitter that it has been submitted before, HN explicitly allows reposts after a year or so.
Ah, thanks for explaining that. I'm more used to Reddit where re-posting links is more common but also more frowned upon, so I'm still unfamiliar with the culture here.
Sure. Reposts are fine after a year or so. This is in the FAQ: https://news.ycombinator.com/newsfaq.html. The purpose of linking to previous discussions is that many readers are curious to read them.
#undef isn't impure. It isn't an assignment, but an unbinding; it asserts that in the remainder of the translation unit, the preprocessor symbol is not known. That symbol's status in the prior parts of the translation unit hasn't changed.
Rather, there is nesting. Nesting isn't the same thing as scoping.
> Variables will always be unbound in the reverse order they were bound.
Counterexample:
(let* ((x 1) (y (* 2 x)) (z (+ x y))) ;; bound in sequence
) ;; unbound in parallel
We could have an unlet operator which introduces a new scope that explicitly removes a binding:
(let (x) ; #define x
(let (y) ; #define y
(unlet (x) ; #undef x
;; y bound, x free
))) ; #undef y, #undef x
Basically, #define and #undef can be regarded as having proper nesting: each one creates a new scope that lasts unti the end of the translation unit, nested relative to the previous scope.
Interesting article indeed. If anyone was curious and wanted to drill down to the source of the "Scala is Not a Functional Programming Language" discussion, surprise, the link is dead. Here's an archive link: http://web.archive.org/web/20090517065705/http://enfranchise...
If you don't have that interrupt in your brain that fires when you read something so outlandish that it surely must be deliberately provocative, you're going to spend a lot of time very upset about articles from The Onion.
On a different note, the book "Functional C" teaches C programming to ML functional programmers. Quite interesting and gives a new perspective to C programmers on their favourite language.
> "Sadly–and here is the real intent behind my post–many Haskell programmers believe that IO is necessary to do “real programming”, and they use Haskell as if it were C (relegating lots of work to IO). In other words, monadic IO has proved to be such a comfortable “solution” to I/O in a functional language, that very few folks are still searching for a genuinely (not merely technically) functional solution. Before monadic IO, there was a lot of vibrant and imaginative work on functional I/O. It hadn’t arrived yet, but was still in touch with the Spirit of functional programming. With the invention and acceptance of monadic imperative programming, it’s like the Haskell community wandered into an opium den and are still lying there in a fog.
> [...]
> "By relating Haskell+IO to cpp+C, I’m not trying to lower the former or elevate the latter. Instead, I’m trying to waken functional programmers out of the opium fog and remind them how fun and creative genuinely functional programming can be."
I love Haskell but I'm not well-versed enough to know why other alternatives to monadic IO were discarded. I do know Haskell predates the IO monad.