Why is the tail call optimization not used in this

2019-04-08 00:18发布

The following program blows the stack:

__find_first_occurrence :: (Eq b) => b -> [b] -> Int -> Int
__find_first_occurrence e [] i = -1
__find_first_occurrence e (x:xs) i
    | e == x = i
    | otherwise = __find_first_occurrence e xs (i + 1)

find_first_occurrence :: (Eq a) => a -> [a] -> Int
find_first_occurrence elem list =   
    __find_first_occurrence elem list 0

main = do
    let n = 1000000
    let idx = find_first_occurrence n [1..n]
    putStrLn (show idx)

Fails with

Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize -RTS' to increase it.

However, as far as I understand it, the possible recursive call to __find_first_occurrence is the last thing evaluated by __find_first_occurrence, hence tail call optimization should be possible to do.

1条回答
成全新的幸福
2楼-- · 2019-04-08 00:50

The tail call optimization is used, but the (i+1) expressions get thunked, and evaluating them at the end causes the stack to overflow.

查看更多
登录 后发表回答