在编程练习中,首先要求对阶乘函数进行编程,然后计算和: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