首先要注意的是,代码本身什么也不做。它只是一堆数学表达式,在我们尝试从中提取一些值之前,它的循环程度并不重要。我们如何做到这一点?
我们可以这样做:
print $ take 1 primes1
这里没有问题。我们可以在不查看任何递归代码的情况下获取 primes1 的第一个值,它明确地作为 2 存在。那么:
print $ take 3 primes1
让我们尝试扩展primes1 以获取一些值。为了保留这些
表达式易于管理,我现在忽略了 print 和 take 部分,但是
请记住,我们只是因为他们才做这项工作。 primes1 是:
primes1 = 2 : filter prime [3..]
我们有我们的第一个值,我们的第一步是扩展过滤器。
如果这是一种严格的语言,我们将首先尝试扩展 [3..] 并得到
卡住。过滤器的一个可能定义是:
filter f (x:xs) = if f x then x : filter f xs else filter f xs
给出:
primes1 = 2 : if prime 3 then 3 : filter prime [4..] else filter prime [4..]
我们的下一步必须弄清楚prime 3 是真还是假,所以让我们
使用我们对prime、ldp 和ldpf 的定义来扩展它。
primes1 = 2 : if ldp 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
primes1 = 2 : if ldpf primes1 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
现在,事情变得有趣了,primes1 引用自己,而 ldpf 需要第一个值
做它的计算。幸运的是,我们可以轻松获得第一个值。
primes1 = 2 : if ldpf (2 : tail primes) 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
现在,我们在 ldpf 中应用保护子句并找到 2^2 > 3,因此找到 ldpf (2 : tail primes) 3 = 3。
primes1 = 2 : if 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
primes1 = 2 : 3 : filter prime [4..]
我们现在有了第二个值。请注意,我们评估的右侧从未变得特别大
并且我们不需要很远地遵循递归循环。
primes1 = 2 : 3 : if prime 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : if ldp 4 == 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : if ldpf primes1 4 == 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : if ldpf (2 : tail primes1) 4 == 4 then 4 : filter prime [5..] else filter prime [5..]
我们使用保护子句rem 4 2 == 0,因此我们在这里得到2。
primes1 = 2 : 3 : if 2 == 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : filter prime [5..]
primes1 = 2 : 3 : if prime 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldp 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldpf primes1 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldpf (2 : tail primes) 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
没有守卫匹配,所以我们递归:
primes1 = 2 : 3 : if ldpf (tail primes) 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldpf (3 : tail (tail primes)) 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
现在3^2 > 5,所以表达式是 5。
primes1 = 2 : 3 : if 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : 5 : filter prime [6..]
我们只需要三个值,所以评估可以停止。
那么,现在回答您的问题。惰性列表是只需要我们评估所需内容的列表,并且
2 有帮助,因为它确保当我们到达递归步骤时,我们总是已经有足够的值
计算出来的。 (想象一下,如果我们不知道 2,扩展这个表达式,我们最终会陷入一个循环
很快。)