[英]How does Haskell evaluate this primes function?
I find it rather difficult to understand how Haskell will evaluate this primes
function. 我发现很难理解Haskell如何评估此primes
函数。 Is the primes
function get evaluated over and over, or the primes
in the primeFactors
function will point back to the first primes
? primes
函数是一遍又一遍地求值,还是primeFactors
函数中的primes
会指向第一个primes
?
primes = 2 : filter ((==1) . length . primeFactors) [3,5..]
primeFactors n = factor n primes
where
factor n (p:ps)
| p * p > n = [n]
| n `mod` p == 0 = p : factor (n `div` p) (p:ps)
| otherwise = factor n ps
main :: IO ()
main = print $ length . take 100000 $ primes
primes
is just a list. primes
只是一个列表。 Its first element is 2, and the rest of the elements are taken from the list of odd integers filtered by (in part) the function primeFactors
. 它的第一个元素为2,其余元素取自使用(部分)函数primeFactors
过滤的奇整数列表。
primeFactors
, though, uses primes
. primeFactors
使用primes
。 Isn't this circular? 这不是通函吗?
Not quite. 不完全的。 Because Haskell is lazy, primeFactors
doesn't need all the values in primes
at once, just the ones that are less than or equal to the square root of its argument ( p:ps
matches against primes
, but we only need ps
if p*p <= n
), and those primes were all found by previous calls to primeFactors
. 由于Haskell是惰性的,因此primeFactors
不需要一次使用primes
所有值,而只需要小于或等于其参数平方根的值( p:ps
与primes
匹配,但仅当p*p <= n
时才需要ps
p*p <= n
),这些素数都是通过先前对primeFactors
调用找到的。
As an example, trace the first few calls to primeFactors
. 例如,跟踪对primeFactors
的前几个调用。 For brevity, let b = (==1) . length . primeFactors
为简便起见,令b = (==1) . length . primeFactors
b = (==1) . length . primeFactors
b = (==1) . length . primeFactors
. b = (==1) . length . primeFactors
。
primeFactors 3 == factor 3 primes
-- only unpack as much of primes as we need for the next step
== factor 3 (2:filter b [3,5..])
-- because 2*2 > 3, that's only one level
== [3]
And so, since b [3]
is true, we know that 3 is the next element of primes
. 因此,由于b [3]
为真,我们知道3是primes
的下一个元素。 That is, primes = 2:3:filter b [5,7..]
也就是说, primes = 2:3:filter b [5,7..]
primeFactors 5 == factor 5 primes
== factor 5 (2:3:filter b [3,5..])
-- 2*2 > 5 is false, as is 5 `mod` 2 == 0, so
== factor 5 (3:filter b [3,5..])
-- 3*3 > 5, so
== [5]
And b [5]
is true, so 5
is the next element of primes
. b [5]
是正确的,因此5
是primes
的下一个元素。
primeFactors 7 == factor 7 primes
== factor 7 (2:3:5:filter b [3,5..])
== factor 7 (3:5:filter b [3,5..])
-- 3*3 > 7
== [7]
And b [7]
is true, so 7
is the next element of primes
. b [7]
是正确的,因此7
是质primes
的下一个元素。 (Seems like everything gets added to primes
, doesn't? One more call to primeFactors
will show that isn't the case) (似乎所有内容都添加到质primes
,不是吗?再调用primeFactors
会显示情况并非如此)
primeFactors 9 == factor 9 primes
== factor 9 (2:3:5:7:filter b [3,5..])
-- 2*2 > 9 and 9 `mod` 2 == 0 are false
== factor 9 (3:5:7:filter b [3,5..])
-- 3*3 > 9 is false, but 9 `mod` 3 == 0 is true, so
== 3 : factor (9 `div` 3) (3:5:7:filter b [3,5..])
== 3 : factor 3 (3:5:7:filter b [3,5..])
-- 3*3 > 3 is false, but 3 `mod` 3 == 0, so
== 3 : [3] == [3,3]
But since b [3,3]
is false, 9
is not an element of primes
. 但是由于b [3,3]
为假,所以9
不是 primes
的元素。 So now we have 所以现在我们有了
primes = 2:3:5:7:filter b [3,5..])
It's a long and tedious process to trace this, but you should get the feeling that primes
always stays "ahead" of primeFactors
; 要追踪这个过程是一个漫长而乏味的过程,但是您应该感觉到primes
始终位于primeFactors
“前面”; the elements of primes
that primeFactors
needs have always been determined by earlier calls to primeFactors
. primeFactors
所需的primes
元素始终由先前对primeFactors
调用确定。
how Haskell will evaluate this primes function? Haskell将如何评估该素数函数?
As your code shown in question, it print out first 100000 prime numbers, so how primes
to work? 如问题出你的代码,它打印出第一个10万张素数,所以如何primes
工作?
Firstly, for generating the first prime number, it is simple, just first element of the list: 首先,生成第一个素数很简单,只需列表的第一个元素:
2 : filter ((==1) ...
that is 2
, and for the next one, we need to apply primeFactors
function as 那是2
,对于下一个,我们需要应用primeFactors
函数为
primeFactors 3 = factor 3 primes
and now may confuse someone who new to Haskell, how to evaluate the primes
in above expression? 现在可能会使Haskell的新手感到困惑,如何评估上述表达式中的primes
? the answer is that, it is just a list with elements as [2,...]
, thanks to lazy evaluation, now, we don't need to evaluate all the prime numbers of list generated by primes
function. 答案是,这只是一个元素为[2,...]
的列表,这要归功于惰性求值,现在,我们不需要求值primes
函数生成的所有primes
。 we just need to evaluate next one and look and see what happen. 我们只需要评估下一个 ,然后看看会发生什么。 So, we get 2
, and the above expression become: 因此,我们得到2
,上面的表达式变为:
primeFactors 3 = factor 3 [2,..]
and 和
factor 3 (2:ps) | 2 * 2 > 3 = [3]
So, primeFactors 3
retrun [3]
因此, primeFactors 3
[3]
and, so 所以
2: filter ((==1) . length . primeFactors) 3 = [2,3]
we now successfully generate 2 prime numbers, but we need 100000, and how about next? 我们现在成功地生成了2个质数,但是我们需要100000,接下来呢? Obviously, we apply 5
to below expression: 显然,我们将5
应用于以下表达式:
2: filter ((==1) . length . primeFactors) 5
repeats the procedure as above: 重复上述步骤:
primeFactors 5 = factor 5 [2,3,..]
and this time we have 2 elements in the list: 这次我们在列表中有2个元素:
factor 5 [2,3..]
and 和
factor 5 [2,3..] | otherwise = factor 5 [3,...]
and 和
factor 5 [3,...] | 3 * 3 > 5 = [5]
and repeat again and again till to generate 100000 prime numbers, and again, due to lazy evaluation, we don't need 100001 prime number, so the computation stop and print out the result. 然后一次又一次重复直到生成100000个质数,再一次,由于懒惰的求值,我们不需要100001个质数,因此计算停止并打印出结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.