简体   繁体   English

Haskell如何评估该素数函数?

[英]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:psprimes匹配,但仅当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]是正确的,因此5primes的下一个元素。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM