Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering an infinite list in Haskell

Tags:

list

haskell

I have the following code that implements the Sieve of Eratosthenes:

primes :: [Int]
primes = primes' [2..]

primes' :: [Int] -> [Int]
primes' [] = []
primes' (p:ps) = p:(primes' [p' | p' <- ps, not (p' `isMultiple` p)])

a `isMultiple` b = (a `mod` b) == 0

main = print (sum (primes' [2..100000]))

I would like to change main to something like

main = print (sum [p | p <- primes, p < 100000]))

Not surprisingly, this hangs because it must compare p against every element of the infinite list primes. Since I know that primes is in increasing order, how do I truncate the infinite list as soon as I find an element that exceeds my upper limit?

p.s. In theory, primes' filters the input list to return a list of primes. I know there will be some issues if I start the list at something other than 2. I'm still working on how to address this issue on my own, so please no spoilers. Thanks ;-)

like image 278
Code-Apprentice Avatar asked Jun 07 '12 17:06

Code-Apprentice


1 Answers

In cases like this where you know that once the predicate returns false for an element, it won't ever return true for a later element, you can replace filter with takeWhile, which stops taking elements as soon as the predicate returns false for the first time.

like image 140
sepp2k Avatar answered Oct 05 '22 01:10

sepp2k