
Hi all. I provide a sample program which causes a strange behavior of strictness analyzer. variant 1 {{{ module StrictUnusedArg (main) where f2 :: Int -> Int -> Int f2 x1 = if x1 == 0 then (\x0 -> x0) else let y = x1 - 1 in f3 y y f3 :: Int -> Int -> Int -> Int f3 x2 = if x2 == 0 then f2 else let y = x2 - 1 in f4 y y f4 :: Int -> Int -> Int -> Int -> Int f4 x3 = if x3 == 0 then f3 else let y = x3 - 1 in \x2 x1 x0 -> f4 y x2 x1 (y + x0) main = print (f2 100 0) }}} I expect that all arguments will be unboxed. "-ddump-simpl" reveals that actually types are {{{ f2 :: Int# -> Int -> Int f3 :: Int# -> Int -> Int -> Int }}} So when "f3" calls "f2" it unboxes the argument named "x1" and when "f2" calls "f3" it boxes the argument named "x1". "-ddump-stranal" knows strictness only for the "x2" of "f3" and "x1" of "f2". {{{ f2: [Arity 1 Str: DmdType U(L)] f3: [Arity 1 Str: DmdType U(L)] }}} I also can force the analyzer to think that "x1" and "x0" are strict by eta-expanding "f3": variant 2 {{{ f3 x2 x1 x0 = if x2 == 0 then f2 x1 x0 else let y = x2 - 1 in f4 y y x1 x0 }}} "-ddump-stranal" yields: {{{ f3: [Arity 3 Str: DmdType U(L)U(L)U(L)m] f2: [Arity 2 Str: DmdType U(L)U(L)m] }}} I even do not use ($!). So, the questions: Is it possible to change the strictness analyzer so it will treat "variant 1" as "variant 2"? Are these changes big? Compiled with options: $ ghc --make -fstrictness -fPIC -O3 -fforce-recomp blah-blah-blah $ ghc --version The Glorious Glasgow Haskell Compilation System, version 6.12.1 -- Best regards, Roman Beslik.