在用Haskell实现Eratosthenes的过程中,为什么是3,5,7的倍数。。没有从列表中删除?

在用Haskell实现Eratosthenes的过程中,为什么是3,5,7的倍数。。没有从列表中删除?,haskell,primes,sieve-of-eratosthenes,Haskell,Primes,Sieve Of Eratosthenes,我目前正在自学Doets和Eijck写的《Haskell通往逻辑、数学和编程之路》,我在第三章 在本章中,作者提供了一个Haskell代码来实现Eratosthenes算法的筛子,我不喜欢他们的实现,所以我尝试给出自己的实现;但是,我的代码版本只删除了2的倍数,我无法找出原因。以下是代码: sieve :: [Int] -> [Int] sieve (0:xs) = sieve xs sieve (x:xs) = x : sieve (mark x 2 xs) where mark :

我目前正在自学Doets和Eijck写的《Haskell通往逻辑、数学和编程之路》,我在第三章

在本章中,作者提供了一个Haskell代码来实现Eratosthenes算法的筛子,我不喜欢他们的实现,所以我尝试给出自己的实现;但是,我的代码版本只删除了2的倍数,我无法找出原因。以下是代码:

sieve :: [Int] -> [Int]
sieve (0:xs) = sieve xs
sieve (x:xs) = x : sieve (mark x 2 xs)
 where
 mark :: Int -> Int -> [Int] -> [Int]
 mark n k (y:ys)
  | y == n*k = 0 : (mark n (k+1) ys)
  | otherwise = y : (mark n (k) ys) 
输出是

*Ch3> sieve [2..]
[2,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,...
那么,为什么代码不对其他数字的倍数执行相同的删除操作,例如3,5,7

简短回答:
mark
中的计数器
k
对于
n
>2不递增

标记x2[2..]
正确地从列表中去除even,因此下一步是调用
sieve[3,5..]
,这相当于
3:sieve(标记32[5,7..])
,让我们看看这里发生了什么

标记3 2[5,7..]
(大概)尝试从列表中删除
3
的所有倍数,但它会一步一步地执行此操作,首先尝试从列表中删除6。但是,由于列表中只包含奇数,因此永远不会从列表中删除6,并且第一种情况总是失败。代码继续检查6,从不向上移动以删除9


同样,25也不会被删除,因为代码只会尝试从列表中删除
2*5

谢谢您的回答。我现在已经改变了代码的实现,它现在可以工作了