Repeated computations under a lambda

Joachim Breitner mail at
Tue Jul 18 22:44:24 UTC 2017

Hi Conal,

Am Dienstag, den 18.07.2017, 15:35 -0700 schrieb Conal Elliott:
> Thanks very much for this reply, Joachim. I see that `-fno-do-lambda-
> eta-expansion` with my example prevents moving the computation under
> the lambda where it gets repeatedly evaluated. I don't understand
> what this code motion/substitution has to do with eta-expansion. Is
> it that the `let` expression itself is eta-expanded? The GHC Users
> Guide describes this flag as "eta-expand let-bindings to increase
> their arity", which doesn't seem to fit here, since the `let`-
> bindings are not function-valued (though the `let` expression is).

In the code

exampleC :: Double -> Double -> Double
exampleC = \ t -> let s = sin t in \ x -> x + s

the exampleC is the bound things that is eta-expanded. Ok, it is a top-
level function, but that does not make a big difference. When eta-
expanded, it becomes

exampleC :: Double -> Double -> Double
exampleC = \ t y -> (let s = sin
t in \ x -> x + s) y

and from then on, usual simplifications kick in to produce 

exampleC :: Double -> Double -> Double
exampleC = \ t y -> let s = sin t in y + s

and eventually

exampleC :: Double -> Double -> Double
exampleC = \ t y -> y + sin t

(I ignore the unboxing of Doubles here).

> > Did you measure whether this really is a problem? The benefits of not
> > dealing with dynamically allocated functions might outweigh the cost of
> > recalculating sin.
> No, I haven't measured. In this case, I'm compiling Haskell to GLSL
> for execution on a GPU, where the inner lambda will be over space,
> which means at least one application per pixel, so the computations
> moved under the inner lambda will be redundantly computed a few
> millions of times per frame (and much more with anti-aliasing).
> Instead, I want to move those calculations to once per frame and
> stored in quickly accessed video memory. As the space-independent
> computation gets more complex, I expect the saving to grow.

Hmm. The problem is that GHC’s optimizer uses a cost-model (in this
case: calling an anonymous function is worse than recomputing sind)
that does not hold in your case. Besides simply turning off some
transformations, I am not sure what best you could do to avoid this…

Joachim Breitner
  mail at
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <>

More information about the ghc-devs mailing list