# Difference between revisions of "Prime numbers"

From HaskellWiki

(Made sieve more readable) |
CaleGibbard (talk | contribs) |
||

Line 37: | Line 37: | ||

primes, nonprimes :: [Int] |
primes, nonprimes :: [Int] |
||

primes = [2,3,5] ++ (diff [7,9..] nonprimes) |
primes = [2,3,5] ++ (diff [7,9..] nonprimes) |
||

− | nonprimes = foldr1 f |
+ | nonprimes = foldr1 f . map g $ tail primes |

where f (x:xt) ys = x : (merge xt ys) |
where f (x:xt) ys = x : (merge xt ys) |
||

g p = [ n*p | n <- [p,p+2..]] |
g p = [ n*p | n <- [p,p+2..]] |

## Revision as of 12:26, 10 July 2007

The following is an elegant (and highly inefficient) way to generate a list of all the prime numbers in the universe:

```
primes = sieve [2..] where
sieve (p:xs) = p : sieve (filter (\x -> x `mod` p > 0) xs)
```

With this definition made, a few other useful (??) functions can be added:

```
is_prime n = n `elem` (takeWhile (n >=) primes)
factors n = filter (\p -> n `mod` p == 0) primes
factorise 1 = []
factorise n =
let f = head $ factors n
in f : factorise (n `div` f)
```

(Note the use of `takeWhile`

to prevent the infinite list of primes requiring an infinite amount of CPU time and RAM to process!)

The following is a more efficient prime generator, implementing the sieve of Eratosthenes:

```
merge xs@(x:xt) ys@(y:yt) = case compare x y of
LT -> x : (merge xt ys)
EQ -> x : (merge xt yt)
GT -> y : (merge xs yt)
diff xs@(x:xt) ys@(y:yt) = case compare x y of
LT -> x : (diff xt ys)
EQ -> diff xt yt
GT -> diff xs yt
primes, nonprimes :: [Int]
primes = [2,3,5] ++ (diff [7,9..] nonprimes)
nonprimes = foldr1 f . map g $ tail primes
where f (x:xt) ys = x : (merge xt ys)
g p = [ n*p | n <- [p,p+2..]]
```

`nonprimes`

effectively implements a heap, exploiting Haskell's lazy evaluation model. For another example of this idiom see the Prelude's `ShowS`

type, which again exploits Haskell's lazy evaluation model
to avoid explicitly coding efficient concatenable strings. This is generalized by the DList package.