The C language is purely functional (2009)
conal.net
conal.net
> "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.
Here is some research on it: https://www.microsoft.com/en-us/research/publication/koka-pr...
My favourite title is "I am not a number, I am a free variable"
https://scholar.google.com/citations?user=vO7qGKwAAAAJ&hl=en...
This recent paper by Oleg Kiselyov ("Effects Without Monads: Non-determinism Back to the Meta Language" https://arxiv.org/abs/1905.06544 https://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.
The ICFP presentation "Automatically escaping Monads" is also interesting https://www.youtube.com/watch?v=wG8AErq6Bbo http://benl.ouroborus.net/talks/2016-HIW-Escape.pdf
“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.
and in 2009: https://news.ycombinator.com/item?id=618817
I chuckled.
Consider that lambda or let will also unbind:
(let ((x 3)) ; #define x 3
) ; #undef x, effectivelyYou can do something like this in c:
#define x 3
#define y 4
#undef x
// more stuff
#undef y
Which is essentially equivalent to [(])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. #define int const int
#define float const float
etc...
It makes for some interesting patterns