1

I should write a function that sums elements in a list comprehension block.

Let's take these two functions just for example:

letSum :: [Int] -> [Int]
letSum xs = [result | x <- xs, y <- xs, let result = x + y, result > 10]

normalSum  :: [Int] -> [Int]
normalSum xs = [x + y | x <- xs, y <- xs, x + y > 10]

Question:

  • Is the second function summing x and y twice in opposite to the first one?
  • If not, how does it work?
radrow
  • 6,419
  • 4
  • 26
  • 53
mkUltra
  • 2,828
  • 1
  • 22
  • 47

1 Answers1

7

The second function will compute the sum twice – there is no explicit sharing to be performed here, nor the Haskell performs memoization (source: When is memoization automatic in GHC Haskell?)

let lets the sum be computed once and used in several places, so the first function will be slightly faster.


EDIT:

Someone in the comments mentioned CSE (common subexpression elimination) as possible optimization that may occur here. I have tried compiling your function with -ddump-cse to discover whether it will happen, but although I didn't find any mentions of normalSum, the output was too mysterious to me. However, my answer should be true if you build your function without -O* flag. I will update my answer if I find more information about it.

radrow
  • 6,419
  • 4
  • 26
  • 53
  • 3
    I’m not sure it’s computed twice. Doing CSE would compute it just once, or even just using cheap strictness (which ghc does). – augustss Feb 24 '19 at 18:18
  • I could not find any information when exactly is CSE performed – radrow Feb 24 '19 at 18:33
  • Ghc does very little CSE, but it does use cheap strictness. Comparing the core for the two functions is the way to find out. – augustss Feb 24 '19 at 19:10