您的代碼在其內部具有一個指數爆炸:
sieve p (x:xs) | rem x p == 0 = sieve p xs
| otherwise = x : (sieve x $ sieve p xs)
-- ^^^^^^^ here!
-- ^^^^^^^ and here!
您打算內sieve
呼叫通過p
只是繼續過濾,但因爲你使用相同的sieve
功能,它也將啓動新的過濾器因爲它遇到了新的素數 - 但這是完全多餘的,因爲「上」級調用也將啓動同一素數的新濾波器!
sieve 2 [3..]
= 3 : sieve 3 (sieve 2 [4..])
= 3 : sieve 3 (5 : sieve 5 (sieve 2 [6..]))
= 3 : 5 : sieve 5 (sieve 3 (sieve 5 (sieve 2 [6..])))
.... -- ^^^ ^^^ -- !!!
後通過四個sieve
這兒穿過頂端,每一個將在兩創建四個新sieve 7
而分裂,所以會有sieve
S IN的鏈!!更糟的是,當 - 複合! - 經過篩子,將分割,所述 S和,並且將僅由被拒絕。所以它實際上糟糕比指數中的素數n
的數量,並接近最後的黃金的價值是指數產生(這是~ n log(n)
)。
將其更改爲
sieve p (x:xs) | rem x p == 0 = sieve p xs
| otherwise = x : (sieve x $ filter ((>0).(`rem` p)) xs)
,你會得到相當於你舉一個代碼。
如果你喜歡手工代碼的一切,你可以引入一個新的說法,一個布爾標誌控制是否啓動新的過濾器或不:
primes = 2 : sieve True 2 [3..]
sieve b p (x:xs) | rem x p == 0 = sieve b p xs
| b = x : (sieve b x $ sieve False p xs)
| otherwise = x : sieve b p xs
[你應該看看這個(HTTP: //stackoverflow.com/questions/1764163/help-explain-this-chunk-of-haskell-code-that-outputs-a-stream-of-primes#comment1648439_1764163) – 2014-12-04 08:48:18