I have always wondered why I couldn't do something in Haskell like:
{#- 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.
Haskell already does something almost like this. Expressions such as "factorial 5" may be lifted to the top level as a Constant Applicative Form (CAF). This allows the result to be computed once the first time they are needed and then subsequently shared, even across function invocations.
The advantage of this approach over doing it at compile time is that you don't risk blowing up your compilation time.
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.