# LiberateCase and Lambda Dropping

Manuel M. T. Chakravarty chak@cse.unsw.edu.au
Wed, 28 Feb 2001 23:08:58 +1100

```LiberateCase would sometimes benefit from lambda dropping.
As an example, consider the definitions

import PrelGHC
import PrelBase

data AccessPath = Cont  AccessPath
| Value Int

accessLen0#, accessLen1#, accessLen2# :: AccessPath -> Int#
accessLen0# (Value i) = case i of {I# i -> i}
accessLen1# (Cont ap) = accessLen0# ap
accessLen2# (Cont ap) = accessLen1# ap

main = print \$ (I# (demandAll 10# (foo 1# ap)))
where
ap = Cont (Value 10)

foo 0# x = x
foo n# x = foo (n# -# 1#) x

and the following two variants of `demandAll'.  The first
one is optimised perfectly by LiberateCase

demandAll       :: Int# -> AccessPath -> Int#
demandAll n# ap  = demandAll' n#
where
demandAll' n# = let
v = accessLen1# ap
in
case n# of
0# -> v
n# -> v +# demandAll' (n# -# 1#)

but the second one

demandAll       :: Int# -> AccessPath -> Int#
demandAll n# ap  = let
v = accessLen1# ap
in
case n# of
0# -> v
n# -> v +# demandAll (n# -# 1#) ap

is compiled to the inefficient

Main.demandAll :: (PrelGHC.Int# -> Main.AccessPath -> PrelGHC.Int#)
[Constant] __A 2 PS
Main.demandAll
= \ n# :: PrelGHC.Int# ap :: Main.AccessPath ->
case ap of wild {
Main.Value a -> PrelErr.patError @ PrelGHC.Int# lvl_s1Ky;
Main.Cont ap1 ->
case ap1 of wild1 {
Main.Cont a -> PrelErr.patError @ PrelGHC.Int# lvl1_s1Kx;
Main.Value i ->
case i of wild2 { PrelBase.I# i1 ->
case n# of ds {
0 -> i1;
__DEFAULT -> PrelGHC.+# i1 (Main.demandAll (PrelGHC.-# ds 1) wild)
}
}
}
}

Generally, arguments that remain constant in a recursive
function should be lambda dropped, I think.

Cheers,
Manuel

PS: This is not posing a big problem, but it is somewhat
annoying as I regularly attempt to write the more
concise form.

```