Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partially evaluating right-handed operator sections

I have a function (*~). Most of the cost of evaluating x *~ y comes from inspecting the second argument, roughly along these lines:

(*~) :: a -> b d -> c d a
x *~ y = case y' of
           Bar -> cheapFunction y' x
           Baz -> cheapFunction2 y' x
           Quux -> cheapFunction3 y' x
  where
    y' = expensive y

Is there some way to convince GHC to partially evaluate operator sections like (*~ y)?

I tried rewriting it like:

(*~) = flip go
  where
    go y = let y' = expensive y
            in case y' of
                 Bar -> cheapFunction y'
                 Baz -> cheapFunction2 y'
                 Quux -> cheapFunction3 y'

but it didn't seem to help. I think this might be because flip requires all it's arguments before it does the flipping?

One way would just be to flip the operator itself, but it reads much more naturally when the expensive operand is on the right hand side, because it lines up with an existing notation.

Can a properly crafted {-# RULE #-} bail me out here? If so, what should it say? (I'm unclear on how far the sectioning syntax will have been desugared before rules look for matches, among other things.)

like image 881
Doug McClean Avatar asked Oct 21 '15 20:10

Doug McClean


1 Answers

To trigger such an optimization you need to make sure that your function gets inlined. Place the {-# INLINE (*~) #-} pragma before the declaration of the (*~) function. I can't guarantee you that it'll solve your problem, but it's the only way I see it being approached. I'd examine the generated Core code with a tool like "ghc-core" afterwards to make sure.

However, your problem actually is just an indication of improper code composition. Your function is doing multiple unrelated things. expensive y should simply be factored out of it, then your problem will be erased as such. I.e., the usage pattern should be x *~ expensive y instead of x *~ y.

like image 58
Nikita Volkov Avatar answered Nov 02 '22 02:11

Nikita Volkov