Float out prevents RULES from firing.
Motivation
Consider this function and rule:
foo :: Int -> Bool
foo x = L.elem x [1,2::Int]
{-# RULES
"elem/build" [2] forall x (g :: forall b . (Int -> b -> b) -> b -> b)
. L.elem x (build g) = g (\ y r -> (x == y) || r) False
#-}
If compiled with -O -fno-full-laziness this fires as expected and produces:
foo
= \ (x_ay4 :: Int) ->
case x_ay4 of { I# x1_a1rE ->
case x1_a1rE of {
__DEFAULT -> GHC.Types.False;
1# -> GHC.Types.True;
2# -> GHC.Types.True
}
}
which is what we want.
If we compile using -O we get after FloatOut during the InitialPhase:
lvl_s1vK :: forall b. (Int -> b -> b) -> b -> b
lvl_s1vK
= \ f xs ->
f 1 (f 2 xs)
list :: [Int]
list = build lvl_s1vK
foo :: Int -> Bool
foo = \ x -> L.elem x list
However we never match on L.elem x list
even though it would match the rule if the referenced bindings where inlined.
Proposal
I'm not sure how this would be best addressed.