Haskell Space Overflow

后端 未结 4 977
情深已故
情深已故 2020-12-10 05:51

I\'ve compiled this program and am trying to run it.

import Data.List
import Data.Ord
import qualified Data.MemoCombinators as Memo

collatzLength :: Int -&g         


        
4条回答
  •  醉酒成梦
    2020-12-10 06:13

    As the author of the code in question, I am now slightly embarrassed because it has not one but two possible stack overflow bugs.

    1. It uses Int. On a 32-bit system this will overflow, as the Collatz sequence can go quite a bit higher than the starting number. This overflow can cause infinite recursion as the function jumps back and forth between negative and positive values.

      In the case of numbers between one and a million, the worst starting point is 704511, which goes as high as 56,991,483,520 before coming back down towards 1. This is well outside the 32-bit range.

    2. It uses maximumBy. This function is not strict, so it will cause a stack overflow when used on long lists. One million elements is more than enough for this to happen with the default stack size. It still works with optimizations enabled, though, due to the strictness analysis performed by GHC.

      The solution is to use a strict version. Since none is available in the standard libraries, we can use the strict left fold ourselves.

    Here is an updated version which should (hopefully) be stack overflow-free, even without optimizations.

    import Data.List
    import Data.Ord
    import qualified Data.MemoCombinators as Memo
    
    collatzLength :: Integer -> Integer
    collatzLength = Memo.arrayRange (1,1000000) collatzLength'
      where
        collatzLength' 1 = 1
        collatzLength' n | odd n  = 1 + collatzLength (3 * n + 1)
                         | even n = 1 + collatzLength (n `quot` 2)
    
    main = print $ foldl1' max $ [(collatzLength n, n) | n <- [1..1000000]]
    

提交回复
热议问题