3

After a long while dealing with other languages, I wanted to refresh my aging Haskell skills a little with some codegolf inspired computation (which is intended to be lengthy). In the code below, I relied on lazy computation - but instead of a result, the machine ran out of memory...

import Data.Word

kernel :: (Word32,Word32) -> Word32
kernel (i,j) = div (i*j) 3

result :: Word32
result = sum (fmap kernel
              [(i,j) |
               i <- [0 :: Word32 .. 10000],
               j <- [0 :: Word32 .. 10000]])

So my questions are:

  • Is the list comprehension here not supposed to be lazy and then lazily provide data to fmap and eventually sum?
  • How else would I do it idiomatically? (I know, I could do a tail recursion implementation but that appears a bit too low level here).
Will Ness
  • 70,110
  • 9
  • 98
  • 181
BitTickler
  • 10,905
  • 5
  • 32
  • 53
  • In a way, yes. I will check, if the compiled version behaves the same as if I `:load` the source into ghci. – BitTickler Oct 10 '21 at 16:17
  • 1
    The better solution is to use `foldl'` instead of `sum`. – interjay Oct 10 '21 at 16:20
  • the `foldl'` version of the above code works also in ghci. But the result value is not as expected. It is supposed to produce the same output as the c++ code: `extern "C" uint32_t c_result() { uint32_t s,i,j; for (s = UINT32_C(0), i = UINT32_C(0); i < UINT32_C(10000);i++) { for (j = UINT32_C(0); j < UINT32_C(10000); j++) { s += (i*j) / UINT32_C(3); } } return s; }` – BitTickler Oct 10 '21 at 16:32
  • 1
    Haskell ranges are inclusive. – interjay Oct 10 '21 at 16:43
  • 1
    Could not reproduce. After adding `main = print result`, and compiling with `ghc -O2`, I get a program that runs in 0.9s and uses 9MB max residency. (And, btw, code review: `sum [div (i*j) 3 | ...]` would be more idiomatic.) – Daniel Wagner Oct 10 '21 at 18:26
  • 1
    @interjay GHC is smart enough to `foldl'` when you write `sum`. You just have to tell it you want it to be smart... by compiling with `-O2`. – Daniel Wagner Oct 10 '21 at 18:27
  • @DanielWagner If a program eats all your memory and crashes when you run without optimizations (or in the interpreter), I consider that a bug. – interjay Oct 10 '21 at 18:52
  • @interjay I mainly fell into that trap because currently I mostly do Common Lisp with SBCL, which ALWAYs compiles (and optimizes) in the repl if I reload a source file. – BitTickler Oct 10 '21 at 18:56

0 Answers0