我带来了以下Sieve of Eratosthenes实施:
sieve :: (Integral a) => [a] -> [a]
sieve [] = []
sieve (p:ps) = p:[x | x <- sieve ps, (rem x p) /= 0]
primes :: (Integral a) => [a]
primes = sieve [2..100]
从primes
打电话gchi
打印:
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
从 p 2 添加optimization step起始标记号,我最终得到以下代码:
sieve :: (Integral a) => [a] -> [a]
sieve [] = []
sieve (p:ps) = p:[x | x <- sieve ps, x > p ^ 2, (rem x p) /= 0]
primes :: (Integral a) => [a]
primes = sieve [2..100]
但它会产生以下输出:
[2]
我是Haskell的新手,所以我很难理解为什么添加 x > p ^ 2
会产生这个结果。
你能否通过解释Haskell如何评估该表达式来发现我的错误?
答案 0 :(得分:2)
你有
sieve [2..10]
扩展到
2 : [x1 | x1 <- sieve [3..10], x1 > 4, rem x1 2 /= 0]
= 2 : [x1 | x1 <- 3 : [x2 | x2 <- sieve [4..10],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
首先x1
是3
,但3 > 4
是False
,所以我们转到下一个:
= 2 : [x1 | x1 <- [x2 | x2 <- sieve [4..10],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
= 2 : [x1 | x1 <- [x2 | x2 <- 4 : [x3 | x3 <- sieve [5..10],
x3 > 16,
x3 `rem` 4 /= 0],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
因此如果x2
为4
,x2 > 9
为false,那么我们将移至下一个元素:
= 2 : [x1 | x1 <- [x2 | x2 <- [x3 | x3 <- sieve [5..10],
x3 > 16,
x3 `rem` 4 /= 0],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
所以我们已经看到,我们知道返回的唯一实际值是2
,3
被跳过,因为3 > 4
是False
。 4
被跳过,但由于错误的原因,5
将被跳过,因为5 > 16
为False
,依此类推。这里的问题是您的条件x > p ^ 2
会过滤整个列表,但您确实想要在列表中跳转。这意味着您实际感兴趣的值将从输出中过滤掉。
答案 1 :(得分:1)
这行代码:
p:[x | x <- sieve ps, x > p ^ 2, (rem x p) /= 0]
说&#34;从sieve ps
获取所有x,x > p^2
和x
不能被p
&#34;整除。这意味着所有小于或等于p^2
的数字都会被丢弃。这显然不正确(最小的反例:[2..3]
)。