How would one implement a list of prime numbers in Haskell so that they could be retrieved lazily?
I am new to Haskell, and would like to learn about practical uses of t
The accepted answer from @nikie is not very efficient, is gets relatively slow after some thousands, but the answer of @sleepynate is much better. It took me some time to understand it, therefore here is the same code, but just with variables named more clearly:
lazyPrimes :: [Integer]
lazyPrimes = 2: 3: calcNextPrimes (tail lazyPrimes) [5, 7 .. ]
where
calcNextPrimes (p:ps) candidates =
let (smallerSquareP, (_:biggerSquareP)) = span (< p * p) candidates in
smallerSquareP ++ calcNextPrimes ps [c | c <- biggerSquareP, rem c p /= 0]
The main idea is that the candidates for the next primes already contain no numbers that are divisible by any prime less than the first prime given to the function. So that if you call
calcNextPrimes (5:ps) [11,13,17..]
the candidate list contains no number, that is divisible by 2
or 3
, that means that the first non-prime candidate will be 5 * 5
, cause 5* 2
and 5 * 3
and 5 * 4
are already eliminated. That allows you to take all candidates, that are smaller than the square of 5 and add them straight away to the primes and sieve the rest to eliminate all numbers divisible by 5.