在編程練習中,首先要求對階乘函數進行編程,然後計算和:1! + 2! + 3! +... n!
,O(n)
乘法(因此我們不能直接使用階乘)。我不是在尋找解決這個特定(微不足道)問題的方法,我試圖探索Haskell的能力,這個問題是我想玩的玩具。Haskell的懶惰是Python生成器的優雅替代品嗎?
我認爲Python的生成器可能是這個問題的一個很好的解決方案。例如:
from itertools import islice
def ifact():
i , f = 1, 1
yield 1
while True:
f *= i
i += 1
yield f
def sum_fact(n):
return sum(islice(ifact(),5))
然後我試圖找出是否有東西在Haskell比該發生器類似的行爲,我認爲懶惰做所有的工作人員沒有任何額外的概念。
例如,我們可以用
fact = scan1 (*) [1..]
取代我的Python ifact進而解決行使如下:
sum n = foldl1 (+) (take n fact)
我不知道如果這個解決方案是真正的「等效」 Python的一個關於時間複雜度和內存使用。我會說Haskell的解決方案從不存儲所有列表的事實,因爲它們的元素只被使用一次。
我是對的還是完全錯的?
編輯: 我應該檢查更精確:
Prelude> foldl1 (+) (take 4 fact)
33
Prelude> :sprint fact
fact = 1 : 2 : 6 : 24 : _
所以(我的執行)哈斯克爾存儲結果,即使它不再使用。
有一些相似之處,但也有一些不同之處:Python生成器不允許您訪問以前訪問過的元素,除非您明確地將它們存儲在某個其他對象中。 – pyon
與Python風格的生成器(C#:'IEnumerator',Rust:'Iterator'等)最接近的模擬我能想到的是'Producer'的概念,在Gabriel Gonzalez的優秀[pipes](http:/ /hackage.haskell.org/package/pipes)庫。 – pyon
我會說他們在某種程度上更像是它們的概括,但是Python的生成器也可以作爲協同程序,在非常特殊的情況下它們相當不錯。 – bheklilr