How do I define the sieve function for prime computation using higher–order functions?

两盒软妹~` 提交于 2019-12-11 05:11:58

问题


I have a recursive definition of sieve in Haskell for prime number computation. But I don’t know how to write the same function using higher–order functions such as map or filter. Can anybody show me please?

sieve [] = []
sieve (x:xs) = check (x:xs)

check [] = []
check (x:xs)
        |x/=2 && x/=3 && x/=5 && x/=7 = comp (x:xs)
        |otherwise    = x : sieve xs

comp [] = []
comp (x:xs)
        |x `mod` 2 == 0 = sieve xs
        |x `mod` 3 == 0 = sieve xs
        |x `mod` 5 == 0 = sieve xs
        |x `mod` 7 == 0 = sieve xs
        |otherwise      = x : sieve xs

回答1:


With map and filter and iterate; very slow:

primes = map head $ iterate (\(x:xs)-> filter ((> 0).(`rem`x)) xs) [2..]

with addition of concat; much faster and with much improved complexity:

primes = concat $ map fst $ iterate (\(_,(p:ps,xs)) -> case span (< p*p) xs of
            {(h,t) -> (h,(ps, filter ((> 0).(`rem`p)) t))}) ([2],(primes,[3..]))

more at http://www.haskell.org/haskellwiki/Prime_numbers_miscellaneous#One-liners.


You can express iterate through map if you prefer:

iterate f x = let r = x : map f r in r

and filter too:

filter f xs = concat $ map (\x -> [x | f x]) xs

But for the true sieve of Eratosthenes, - one which does not detect composites by divisibility testing but generates them directly from primes it finds, and finds the primes in gaps between thus generated composites, - we need some more auxiliary functions, like minus and union, and treelike-folding foldi (foldr can be used in place of foldi but with decreased speed and worsened complexity):

primes = 2 : _Y ((3:) . minus [5,7..]     
                         . foldi (\(x:xs) ys-> x : union xs ys) [] 
                            . map (\p-> [p*p, p*p+2*p..]))
_Y g = g (_Y g) 

This runs yet faster, at close to best empirical orders of growth achievable with Haskell's immutable code. Immutable arrays can be faster, but they are excluded here because a. it's not in the question, and b. their performance is determined by a given Haskell implementation, not a user code. Mutable arrays are of course the fastest but the code is even more involved.




回答2:


I threw this together quickly, the speed isn't that great, but it is really easy to implement.

primes'::[Int]->[Int]
primes' [] = []
primes' (x:xs) = x:primes (filter ((/= 0) . (`mod` x)) xs)

main = print $ primes [2..20] -- always input a contiguous list from 2 to N.


来源:https://stackoverflow.com/questions/20393703/how-do-i-define-the-sieve-function-for-prime-computation-using-higher-order-func

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!