module Primes where import List -- 1. version, sieve primes = sieve [2..] where sieve (x:xs) = x : sieve [ n | n <- xs , n `mod` x > 0 ] -- 2. version: keep an "upto-date" list of the non-primes -- (a finite list of inifinite lists) -- and calculate the primes from them. primes' = mkPrimes [] [2..] where mkPrimes non_primes (x:xs) | null withX = x : mkPrimes (mult x : non_primes) xs | otherwise = mkPrimes (map tail withX ++ withoutX) xs where (withX,withoutX) = partition ((==x). head) non_primes mult x = iterate (+x) (x+x) -- 3. version: primes and non-primes are mutually recursive. primes'' = 2 : diff [3..] non_primes non_primes = merge (map mult primes'') where mult x = iterate (+x) (x+x) merge ((x:xs):rest) = x : merge (rearrange (xs:rest)) rearrange l@(xl@(x:xs):(y:ys):rest) | x <= y = l | otherwise = (y:xl) : rearrange (ys:rest) -- set difference for ordered lists - result is also ordered: diff :: Ord a => [a] -> [a] -> [a] diff xl@(x:xs) yl@(y:ys) | x < y = x : diff xs yl | x == y = diff xs yl | x > y = diff xl ys -- 4. version, like 2., but uses a tree to manage non-primse: primes''' = mkPrimes L [2..] where mkPrimes non_primes (x:xs) | null withX = x : mkPrimes (tinsert (mult x) non_primes) xs | otherwise = mkPrimes (foldr tinsert withoutX (map tail withX)) xs where (withX,withoutX) = tpartition [x] non_primes mult x = iterate (+x) (x+x) -- a binary tree: data Tree = N [Integer] Tree Tree | L deriving Show -- rules for placing integer lists: leftof, rightof :: [Integer] -> Tree -> Bool leftof (x:xs) (N (y:ys) _ _) = x <= y rightof (x:xs) (N (y:ys) _ _) = x > y -- rule for matching integer lists: matches :: [Integer] -> Tree -> Bool matches (x:xs) (N (y:ys) _ _) = x == y -- insertion: tinsert :: [Integer] -> Tree -> Tree tinsert xl L = N xl L L tinsert xl t@(N yl t1 t2) | xl `leftof` t = N yl (tinsert xl t1) t2 | xl `rightof` t = N yl t1 (tinsert xl t2) -- extraction & removal in one step: tpartition :: [Integer] -> Tree -> ([[Integer]],Tree) tpartition xl L = ([],L) tpartition xl t@(N yl t1 t2) | xl `matches` t = let (a,b) = tpartition' xl t1 in (yl:a, remove b t2) | xl `leftof` t = let (a,b) = tpartition xl t1 in (a, N yl b t2) | xl `rightof` t = let (a,b) = tpartition xl t2 in (a, N yl t1 b) tpartition' xl L = ([],L) -- check for more matches tpartition' xl t@(N yl t1 t2) | xl `matches` t = let (a,b) = tpartition' xl t1 in (yl:a, remove b t2) | otherwise = ([],t) remove L t2 = t2 remove t1 t2 = let (a,b) = rightmost t1 in N a b t2 rightmost (N yl t1 L) = (yl,t1) rightmost (N yl t1 t2) = let (a,b)=rightmost t2 in (a, N yl t1 b) -- test correctness pdiff = [ (a,b,c,d) | (a,b,c,d)<-zip4 primes primes' primes'' primes''', a /= b || b /= c || c /= d ]