la respuesta aceptada de @nikie no es muy eficiente, se vuelve relativamente lento después de algunos miles, pero la respuesta de @sleepynate es mucho mejor. Me tomó un tiempo para entenderlo, por lo tanto, aquí es el mismo código, pero sólo con las variables con nombre más claramente:
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]
La idea principal es que los candidatos para los próximos números primos ya no contienen números que son divisibles por cualquier primo menor que el primer primo dado a la función. Así que si usted llama
calcNextPrimes (5:ps) [11,13,17..]
la lista de candidatos contiene ningún número, que es divisible por 2
o 3
, eso significa que el primer candidato no prime será 5 * 5
, causar 5* 2
y 5 * 3
y 5 * 4
ya están eliminados. Eso le permite tomar todos los candidatos, que son más pequeños que el cuadrado de 5 y agregarlos directamente a los números primos y tamizar el resto para eliminar todos los números divisibles por 5.
Algo así como http://stackoverflow.com/questions/1764163/help-explain-this-chunk-of-haskell-code-that-outputs-a-stream-of-primes? – kennytm
Considere http://hackage.haskell.org/package/primes –
Todo lo contrario: es una tarea difícil crear una lista de números primos no perezosos en Haskell – vpolozov