6

次のプログラムはスタックを吹き飛ばします:

__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)

で失敗する

スタック スペースのオーバーフロー: 現在のサイズは 8388608 バイトです。それを増やすには、「+RTS -Ksize -RTS」を使用します。

ただし、私が理解している限り、可能な再帰呼び出し__find_first_occurrenceは によって評価される最後のもの__find_first_occurrenceであるため、末尾呼び出しの最適化を実行できるはずです。

4

1 に答える 1

15

末尾呼び出しの最適化が使用されますが、(i+1)式はサンクされ、最後にそれらを評価するとスタックがオーバーフローします。

于 2012-03-14T17:12:49.143 に答える