Del capitulo 3 de The Haskell Road To Logic, Math and Programming:



sieve :: [Integer] -> [Integer]

sieve (0:xs) = sieve xs

sieve (n : xs) = n : sieve ( mark xs 1 n )

	where

	mark :: [Integer] -> Integer -> Integer -> [Integer]

	mark (y:ys) k m | k == m 	= 0 : (mark ys 1 m)

					| otherwise = y : (mark ys (k+1) m)

LLamando a la función con sieve [2..] , nos retorna los números primos por el método de Criba de Eratosthenes.

Lo interesante es pensar en como la lista infinita que se le paso como parámetro es evaluada por Haskell. Si pensamos desde una perspectiva de programación imperativa, es imposible que una función sea procesada por otra función hasta que no haya terminado su procesamiento, entonces como es posible que sieve devuelva resultados si en este caso mark devuelve una lista infinita. Este es un ejemplo de Lazy Evaluation y una muy buena explicación se puede encontrar acá y con más profundidad acá.

Ejercicio 3.39 de THRTLMP

Agrego este ejercicio porque me gusto y es otro ejemplo de Lazy Evaluation. Se nos pide refutar la afirmación de que si p1, p2, … , pk son todos los números primos menores a n, entonces ( p1 . p2 . … . pk ) + 1 es también primo, para todo n perteneciente a los naturales.



filterMinor :: [Integer] -> Integer -> [Integer]

filterMinor [] _ = []

filterMinor (x:xs) n 	| x >= n	= []

			| otherwise = x : filterMinor(xs) n



proveSTforN :: Integer -> Bool

proveSTforN n = prime (product( filterMinor (sieve [2..]) n ) + 1)



proveST :: Bool

proveST = all (==True) (map proveSTforN [1..])

Y para ver los resultados:



proveSTforNShow :: Integer -> (Integer, Integer, Bool)

proveSTforNShow n = (n, a, prime(a)) 

		where

		a = product( filterMinor (sieve [2..]) n ) + 1



proveSTShow :: [(Integer, Integer, Bool)]

proveSTShow = map proveSTforNShow [2..]