2014-02-22 76 views
2

我想採取所有偶數的和< = 1000哈斯克爾懶惰內涵

下面的代碼:

sum [x | x <- [1..1000], even x](我知道它可以用[2,4..1000完成],這是練習)

報告總和爲250500

但是:

sum [x | x <- [1..], even x && x <= 1000]

從未完成,並已被打斷!

我認爲我可以安全地寫出[1..],這是一個無限的列表,因爲Haskell不會去評估它。此外,我認爲它會簡單地由x開始,檢查它們並添加它們。

那麼,爲什麼上述不能產生結果呢?

+0

我還不能肯定,但我認爲問題是,哈斯克爾需要檢查(無限)列表中的每一個元素'[1 ..]'以確保它獲得滿足給定謂詞的所有元素。它不能讓「直覺」的飛躍發現只有前1000個元素才能滿足它。 – chepner

+2

Haskell不是一個定理證明者。它不知道在1000之後不能有一個「<1000」的元素。 – Cubic

+0

是的,現在看起來非常明顯......我可能只是把「||」 x == 100000000'之後...我不知道我是怎麼忽略的...... – corazza

回答

8
sum [x | x <- [1..], even x && x <= 1000] 

轉化爲類似

sum (filter (\x -> even x && x <= 1000) [1..]) 

範圍表達式(或脫,enumFrom)繼續產生價值和filter保持丟棄它們(它不知道再也不會有另一個元素滿足謂詞),但sum永遠不會到達列表的末尾,因此它不能返回結果。要停止儘快評估名單,你看到的第一個值大於1000:

sum (takeWhile (<= 1000) $ filter even [1..]) 
+0

當我評論這個問題時,現在看起來很明顯,我不知道我是如何忽略它的。你能解釋第二個片段中第一個x之前的反斜槓是什麼意思嗎? – corazza

+0

@yannbane:這是一個lambda表達式。它使一個匿名函數採用參數'x'。 –