Morte: an intermediate language for super-optimizing functional programs
haskellforall.com
haskellforall.com
Twitter doesn't use Haskell. The most Haskell I've done there is to write an internal tool in Haskell (A shell-based interface to HDFS). Everybody here knows that it's my mission to introduce Haskell more at Twitter and I have two long plays to do so (Morte is part of one of them).
You would think that it would be easier to introduce Haskell at a Scala-based company because of the strong similarities between the functional half of Scala and Haskell, but it's actually quite the opposite: the marginal benefit of switching to Haskell is smaller so it's harder to make the case to adopt Haskell. This is why you see Haskell take hold more easily in companies programming primarily in languages far-removed from Haskell (like PHP or Python) because then the marginal benefit of switching is much higher.
Anyway, I'm a fan. I'm working on a game engine now with an eye toward it being usable with mvc.
Keep making neat things!
I suspect that I've got some bad conceptual misunderstanding here; but, on the other hand, I also have a hard time believing that, if beta- and eta-reduction alone were sufficient to express such powerful optimisations, it would have taken this long to discover that.
Nothing prevents a turing complete program from entering an infinite loop. A GUI program for example is terminated only when the user decides to, which is impossible to predict.
Yes, this is my point: the proposed super-optimiser would, it seems to me, en passant be solving the halting problem, which means that it can't actually exist (or, at least, can't actually satisfy the stated guarantee).
> Nothing prevents a turing complete program from entering an infinite loop. A GUI program for example is terminated only when the user decides to, which is impossible to predict.
On the level of the lambda-calculus, this is reflected in the corresponding term's having no normal form, in which case the algorithm described (which relies on reducing everything to a normal form) cannot do anything with it.
I believe this is the case. So the article's promise (as I read it) can not hold true in the general case.
On a similar note, just write a program that runs the collatz conjecture and prints the result and a program that prints 1. Run them through Morte. If they compile to the same code, then boom, you've solved the Collatz conjecture :)
http://en.wikipedia.org/wiki/Calculus_of_constructions (What morte is based on)
and
http://en.wikipedia.org/wiki/Normalization_property_(abstrac...
answers the point on Turing completeness.
My concern on the practicality point is that the superoptimizer here really isn't "superoptimizing" so much as super-simplifying. There's a reason modern compilers don't aggressively inline every single function called if they have access to the source code, and for the same reasons they don't aggressively unroll every loop they come across if the loop bounds are known compile time.The tradeoffs of such optimizations are very complicated and hard to reason about because processors are very complicated and hard to reason about.
Within a language like the Calculus of Coinductive Constructions like Morte appears to implement it's not such a strange idea to have normalization.
So, no infinite loops means no Halting Problem means no completeness.
The upside is a larger set of easy-to-perform optimizations, much greater mathematical elegance. The downside is that you cannot directly write an interpreter for a complete language. Though you could write one which halts every N steps and requires user input to continue. In practice, that isn't the worst idea for a repl anyway.
There are a number of general examples, though.
1. You can leave termination guarantees in foreign code up to the programmer using an "unsafe" marker.
2. You can model effects using a monad
3. You can model the whole program as codata which is "driven" by the runtime
4. You can write a compiler of an embedded language in CIC and execute complete programs in, say, C
{#- COMPILECOMPUTE #-}
factorial 0 = 1
factorial n = n * factorial (n - 1)
And have the compiler transform something like "factorial 5" into "120" at compile time, since factorial is a pure function, it seems like that would be doable? Of course you'd have to use your pragmas very judiciously to avoid crazy compile times.But there are some instances where, for code readability, I'd want to say "f 123" rather than whatever "f" evaluates to at 123, since "f 123" shows where the value comes from, but at compile time I'd like that to be optimized out.
P.S. This type of inlining was also discussed at http://stackoverflow.com/questions/19259114/why-are-constant....
The advantage of this approach over doing it at compile time is that you don't risk blowing up your compilation time.
Clearly a mark of good taste.
I thought that this must be a joke, but it looks like it's not far off: http://www.etymonline.com/index.php?term=mortgage.
Where are you from? Are you Portuguese or Brazilian? Did you study Latin?