One thing you can do is ask GHC to translate your Haskell program to STG (with -ddump-stg-final
) which has a much more well-defined and simpler operational semantics.
Without optimizations the example from the stackoverflow question becomes:
func =
\r [x]
let { k = \u [] bat x; } in
let { j = \u [] baz k; } in
let { sat = \u [] let { sat = \u [] bar j; } in + $fNumInt sat j;
} in + $fNumInt sat k;
Which shows that it allocates thunks for k
and j
and for the left operand of +
and then it calls the +
function with the Int
instance of Num
.
With optimizations it is:
$wfunc =
\r [x]
case bat x of k {
__DEFAULT ->
case baz k of j {
__DEFAULT ->
case bar j of {
I# x1 ->
case j<TagProper> of {
I# y ->
case k<TagProper> of {
I# y1 -> case +# [x1 y] of sat { __DEFAULT -> +# [sat y1]; };
};};};};};
func = \r [x] case $wfunc x of ww { __DEFAULT -> I# [ww]; };
Which shows a much more direct evaluation of bat
then baz
then bar
and finally the addition.