如何在其条件中使用不完整的列表

时间:2013-05-22 18:48:47

标签: list haskell list-comprehension


我知道..标题不是很好解释...如果你有一个更好的标题在评论中告诉我..
我正在制作一个素数生成器有趣和学习的目的..
这是我的代码:

divisors x xs = [ y | y <- [1]++xs++[x], x `mod` y == 0]
isPrime x xs = divisors x xs == [1,x]
primeLst = [ x | x <- [2..], isPrime x primeLst]

正如你所看到的那样..我必须在生成新的素数时使用已经生成的质数来减少执行时间..
它并没有工作..
有没有办法制作它?

3 个答案:

答案 0 :(得分:2)

让我们从查看divisors函数开始。这有点正确,只有两个问题:

  1. xs参数应该是什么?从定义来看,它看起来应该是x以下的所有素数 - 让我们把它们称为候选素数。因此,如果x10,则候选素数应为[2,3,5,7]。但是,这不是函数作为参数获得的内容。在您的代码中,xs是素数的无限列表。

  2. 从技术上讲,divisors不会返回所有除数。例如,divisors 16 [2,3,5,7,11,13]不会返回8。但这是一个小小的挑剔。

  3. 因此,如果我们可以使用正确的素数列表调用divisors,那么我们应该没问题,isPrime函数也可以。

    问题在于获得候选素数列表。为清楚起见,我将首先给出代码,然后解释:

    primeLst = 2 : [ x | x <- [3..], isPrime x (takeWhile (\p -> p*p <= x) primeLst)]
    

    我做了两处修改:

    1. 我确保primeLst包含2,并将其粘贴在前面。

    2. 我通过从无限的素数列表中取数来限制候选素数,直到我达到的数字高于我测试的素数的平方根。在这样做时,我稍微改变了候选素数的定义,因此例如26的候选者是[2,3,5]而不是[2,3,5,7,11,13,17,19,23]。但它仍然有效。

    3. 您需要考虑两个问题:

      1. 为什么它仍适用于候选素数的新定义?

      2. 为什么以下代码行不起作用,即使它似乎应该给出候选素数的原始定义?

      3. primeLst = 2 : [ x | x <- [3..], isPrime x (takeWhile (\p -> p < x) primeLst)]
        

        最后一个问题很难,所以如果您有疑问,请在评论中发布。

答案 1 :(得分:2)

dividedBy a b = a `mod` b == 0
isPrime x = null $ filter (x `dividedBy`) $ takeWhile (\y -> y * y <= x) primeLst
primeLst = 2:(filter isPrime [3..])

或者,更详细:

primeLst = 2:(filter isPrime [3..])
  where
    isPrime x = null $ primeDivisors x
    primeDivisors x = filter (x `dividedBy`) $ potentialDivisors x
    potentialDivisors x = takeWhile (\y -> y * y <= x) primeLst
    a `dividedBy` b = a `mod` b == 0

答案 2 :(得分:1)

计算primeLst的至少一个元素需要计算isPrime 2 primeLst,这需要计算divisors 2 primeLst的至少两个元素,这需要至少计算[1]++primeLst++[2]的两个元素,这需要计算primeLst的至少一个元素。不会发生。

您可以制作使用[1]++(primesLessThan x)++[x]的作品,但我没有看到用(primesLessThan x)来定义primeLst的简单方法,这可以避免计算循环。