I wrote the following sieve:
isPrime :: Integer -> [Integer] -> Bool
isPrime n = all (\i -> n `mod` i /= 0)
sieve :: [Integer]
sieve = 2 : [i | i <- [3,5..], isPrime i sieve]
but I don't understand why it gets stuck after the first value. Running take 10 sieve
results in [2,
and nothing happens. It probably has something to do with infinite recursion. May the problem be that sieve
is growing and at the same time it's used inside isPrime
? For that reason I also tried modifying isPrime
as follows, but without success:
isPrime :: Integer -> [Integer] -> Bool
isPrime n = all (\i -> n `mod` i /= 0) . takeWhile (<n)
EDIT: Surprisingly, @Jubobs's modification works:
isPrime :: Integer -> [Integer] -> Bool
isPrime n = all (\i -> n `mod` i /= 0) . takeWhile (\p -> p^2 <= n)
I cannot understand why this version of takeWhile
works while the other does not. I see that with my previous version I tested many unnecessary divisors, but they were in a finite number nontheless.
The code should basically be equivalent to the following Python code:
def is_prime(n, ps):
for i in ps:
if n % i == 0: return False
return True
def sieve():
yield 2
n = 3
ps = [2]
while True:
if is_prime(n, ps):
yield n
ps.append(n)
n += 2