I’ve got the feeling that the answer is yes, and that’s not restricted to Haskell. For example, tail-call optimization changes memory requirements from O(n) to O(l), right?
My precise concern is: in the Haskell context, what is expected to understand about compiler optimizations when reasoning about performance and size of a program?
In Scheme, you can take some optimizations for granted, like TCO, given that you are using an interpreter/compiler that conforms to the specification.
Yes, in particular GHC performs strictness analysis, which can drastically reduce space usage of a program with unintended laziness from O(n) to O(1).
For example, consider this trivial program:
Since
sumdoes not assume that the addition operator is strict, (it might be used with aNuminstance for which(+)is lazy), it will cause a large number of thunks to be allocated. Without optimizations enabled, strictness analysis is not performed.However, if we compile with optimizations enabled, the strictness analyzer will determine that since we’re using the addition operator for
Integer, which is known to be strict, the compiler knows that it is safe to evaluate the thunks ahead of time, and so the program runs in constant space.Note that we can get constant space even without optimizations, if we add the strictness ourselves:
Strictness tends to be a bigger issue than tail calls, which aren’t really a useful concept in Haskell, because of Haskell’s evaluation model.