Are there any 100% pure languages (as I describe in the Stack Overflow post) out there already and if so, could they feasibly be used to actually do stuff? i.e. do they have an implementation? I'm not looking for raw maths on paper/Pure lambda calculus. However Pure lambda calculus with a compiler or a runtime system attached is something I'd be interested in hearing about.
- Anybody can ask a question
- Anybody can answer
- The best answers are voted up and rise to the top
Indeed, as Simon Peyton Jones once stated, Haskell is the finest imperative language out there.
Seriously, purity is not a religious issue. The problem is not that impure functions and mutable data exist. The problems in conventional languages is that often you can't tell impure frm pure and mutable from immutable: not by looking at it, not by compiling it, only by running it.
This is the great advantage that Clean, Haskell (and followers like Frege) have. Conversely, languages like F#, Scala or Clojure that embrace the imperative world and just add the possibility to build something functional alongside suffer from the same problems as the imperative languages, although they may seem very practical indeed.
It seems to me you're trying to reinvent Haskell.
Nice description of how IO is done in Haskell.
You mean monads?
After the first half (M a) prompted the user to provide data (of type a), the second half (a -> M b) is the the "remainder" you describe.
If Haskell allowed you to introspect functions instead of just allowing you to run them, it would also be homoiconic.
I would regard Haskell as 100% pure. And it can certainly get stuff done.
While there are some good debates about what "100% pure" actually means, it is certainly not true that a pure functional language cannot do IO. See also the comp.lang.functional FAQ.
All you have to do to allow IO in a pure language is pass a parameter that represents the state of the world to the program, and return the state of the world as an output. This program has no side effects, is referentially transparent and counts as 100% pure. This is pretty much what Haskell's IO Monad does under the hood.
A special mention perhaps for Clojure, which is definitely a practical language with the entire JVM ecosystem and toolchain to your fingertips. It is clearly not 100% pure (since you can get side effects via the STM managed references, various IO functions or Java interop). However the core language if you avoid these special cases is purely functional. So if you stick to the pure subset of Clojure, you actually have a pretty decent pure functional language for most purposes.
A "pure" language that couldn't do IO couldn't do much. ...after all, even printing a result on the screen is IO. So if you can't see the result of a program, wouldn't it be rather pointless?
You couldn't read files, couldn't listen to sockets, couldn't interact with users, couldn't ask for input... etc. What good would that be?
That said, Haskell is the closest to "pure" (whatever that means) functional programming I know of. Their whole IO system is even made using Monads, which kind of a mix between IO and functional.
I also know of "Clean" which is an academic functional language and sees IO as a transform of a World object if I remember right ...however, this starts to be very exotic.
The key is to understand that people who say "purely functional language" really mean to say "pure functional language" --- a language based on pure functions --- and "purely functional" is a slip of the tongue that's become conventional. The motto is "it's the functions that are pure, not the language".
Now, obviously you can't do I/O with pure functions1. This makes purely functional languages different from impure languages, where a function like (made-up semantics)
could be attributed the type
So the IO monad in Haskell is just a data type. A value of that type represents a list of I/O actions for the program to perform (basically). At runtime, the computer alternates between evaluating that list a little further and executing the actions described. But the evaluation does no I/O! That happens after the value's already been obtained.
1 Without defining additional semantics. You could say "a program is a function of type
You define functions that operate on values over time. Those functions can hold a state, in which case they are called nodes. In Signal, nodes and functions are different kind of processes. But the way the state is defined is by referring to previous values of flow variables.
So you could for example code a state machine by having an internal state variable. At each timestep, the new state is defined as a (pure) function of current inputs and the previous state.
When it comes to compiling those languages into, e.g. C, you get global variables that get overwritten inside a big for loop (the apparent antithesis of pure functional programming), but that's actually perfect in a context where static memory allocation and deterministic runtime execution are required.