Skip to content

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.

Edited by Andreas Klebinger
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information