I am wondering how to optimize this code:
fun n = (sum l, f $ f0 l, g $ g0 l) where l = map h [1..n]
Assuming f , f0 , g , g0 and h are expensive, but creating and storing l extremely expensive.
As indicated, l retained until the returned tuple is fully evaluated or garbage collected. Instead, length l , f0 l and g0 l should be executed whenever any of them are executed, but f and g should be delayed.
It looks like this behavior can be fixed by writing:
fun n = a `seq` b `seq` c `seq` (a, fb, gc) where l = map h [1..n] a = sum l b = inline f0 $ l c = inline g0 $ l
Or very similar:
fun n = (a,b,c) `deepSeq` (a, fb, gc) where ...
We could possibly specify a bunch of internal types to achieve the same effects that look painful. Are there any other options?
In addition, I obviously hope with my inline that the compiler combines sum , f0 and g0 in one loop, which constructs and consumes l each time. I could make it explicit by manually embedding it, but it suck. Are there ways to explicitly prohibit list l and / or forced nesting? Pragmas that cause warnings or errors if addition or merging is possible during the compilation process?
Aside, I wonder why seq , inline , lazy , etc. all are defined as let x = x in x in the prelude. Is it just to give them a definition for the compiler to override?