I need to express the sequence of prime numbers. (struggling with ex 3 in project Euler).
I have happened to this recursive definition:
is_not_dividable_by :: (Integral a) => a -> a -> Bool
is_not_dividable_by x y = x `rem` y /= 0
accumulate_and :: (Integral a) => [a] -> (a -> Bool) -> Bool
accumulate_and (x:xs) (f) = (accumulate_and xs (f)) && f(x)
accumulate_and [] f = True
integers = [2,3..]
prime_sequence = [n | n <- integers, is_prime n]
where is_prime n = accumulate_and
(takeWhile (<n) (prime_sequence))
( n `is_not_dividable_by`)
result = take 20 prime_sequence
str_result = show result
main = putStrLn str_result
Though it compiles well, but when executed, it falls into a loop, and just returns <<loop>>
My problem is that I think that I can freely express recursive definitions in Haskell.
But obviously this definition does not fit with the language at all.
However, when I mentally try to solve the prime_sequence, I think I succeed and grow the sequence, but of course with imperative programming apriori.
What is plain wrong in my recursive definition, that makes this code not work in Haskell ?
The culprit is this definition:
prime_sequence = [n | n <- [2,3..], is_prime n] where
is_prime n = accumulate_and
(takeWhile (< n) (prime_sequence))
( n `is_not_dividable_by`)
Trying to find the head element of prime_sequence (the first of the 20 to be printed by your main) leads to takeWhile needing to examine prime_sequence's head element. Which leads to a takeWhile call needing to examine prime_sequence's head element. And so it goes, again and again.
That's the black hole, right away. takeWhile can't even start walking along its input, because nothing's there yet.
This is fixed easily enough by priming the sequence:
prime_sequence = 2 : [n | n <- [3,4..], is_prime n] where
is_prime n = accumulate_and
(takeWhile (< n) (prime_sequence))
( n `is_not_dividable_by`)
Now it gets to work, and hits the second problem, described in Rufflewind's answer: takeWhile can't stop walking along its input. The simplest fix is to stop at n/2. But it is much better to stop at the sqrt:
prime_sequence = 2 : [n | n <- [3,4..], is_prime n] where
is_prime n = accumulate_and
(takeWhile ((<= n).(^ 2)) (prime_sequence))
( n `is_not_dividable_by`)
Now it should work.
The reason it's an infinite loop is because of this line:
prime_sequence =
[n | n <- integers, is_prime n]
where is_prime n = accumulate_and (takeWhile (< n) prime_sequence)
(n `is_not_dividable_by`)
In order to compute is_prime n, it needs to take all the prime numbers less than n. However, in order for takeWhile to know when to stop taking it needs need to also check for n, which hasn't been computed yet.
(In a hand-wavy manner, it means your prime_sequence is too lazy so it ends up biting its own tail and becoming an infinite loop.)
Here's how you can generate an infinite list of prime numbers without running into an infinite loop:
-- | An infinite list of prime numbers in ascending order.
prime_sequence :: [Integer]
prime_sequence = find [] integers
where find :: [Integer] -> [Integer] -> [Integer]
find primes [] = []
find primes (n : remaining)
| is_prime = n : find (n : primes) remaining
| otherwise = find primes remaining
where is_prime = accumulate_and primes (n `is_not_dividable_by`)
The important function here is find, which takes an existing list of primes and a list of remaining integers and produces the next remaining integer that is prime, then delays the remaining computation until later by capturing it with (:).
Related
I recently started learning Haskell. To train a bit I wanted to try generating the list of prime numbers via self reference using the following code:
main = do
print (smaller_than_sqrt 4 2)
print (smaller_than_sqrt_list 5 [2..])
print ("5")
print (is_prime 5 [2..])
print ("7")
print (is_prime 7 [2..])
print ("9")
print (is_prime 9 [2..])
print ("test")
print (take 5 primes) -- Hangs
-- Integer square root
isqrt :: Int -> Int
isqrt = ceiling . sqrt . fromIntegral
-- Checks if x is smaller than sqrt(p)
smaller_than_sqrt :: Int -> Int -> Bool
smaller_than_sqrt p x = x <= isqrt p
-- Checks if x doesn't divide p
not_divides :: Int -> Int -> Bool
not_divides p x = p `mod` x /= 0
-- Takes in a number and an ordered list of numbers and only keeps the one smaller than sqrt(p)
smaller_than_sqrt_list :: Int -> [Int] -> [Int]
smaller_than_sqrt_list p xs = takeWhile (smaller_than_sqrt p) xs
-- Checks if p is prime by looking at the provided list of numbers and checking that none divides p
is_prime :: Int -> [Int] -> Bool
is_prime p xs = all (not_divides p) (smaller_than_sqrt_list p xs)
-- Works fine: primes = 2 : [ p | p <- [3..], is_prime p [2..]]
-- Doesn't work:
primes = 2 : 3 : [ p | p <- [5..], is_prime p primes]
But for some reason referencing primes inside of primes hangs when running runhaskell and is detected as a loop error when running the compiled binary with ghc.
However I don't really understand why.
Clearly, the first two elements of primes are 2 and 3. What comes after that? The next element of primes is the first element of
[p | p <- [5..], is_prime p primes]
What's that? It could be 5, if is_prime 5 primes, or it could be some larger number. To find out which, we need to evaluate
smaller_than_sqrt_list 5 primes
Which requires
takeWhile (<= isqrt 5) primes
Which requires
takeWhile (<= 3) primes
Well, that's easy enough, it starts with 2:3:..., right? Okay, but what's the next element? We need to look at the third element of primes and see whether it's less or equal to 3. But the third element of primes is what we were trying to calculate to begin with!
The problem is that smaller_than_sqrt 5 3 is still True. To compute whether 5 is a prime, the is_prime 5 primes expands to all (not_divides 5) (takeWhile (smaller_than_sqrt 5) primes), and takeWhile will attempt to iterate primes until the predicate no longer holds. It does hold for the first element (2), it still does hold for the second element (3), will it hold for the next element - wait what's the next element? We're still computing which one that is!
It should be sufficient to use floor instead of ceiling in isqrt, or simpler just
smaller_than_sqrt p x = x * x <= p
This question already has answers here:
Finite comprehension of an infinite list
(3 answers)
Haskell - Why does this list comprehension return an infinite list?
(1 answer)
How to filter an infinite list in Haskell [duplicate]
(4 answers)
Closed 1 year ago.
I have a predefined function "primes" that returns an infinite list of all prime numbers. I wrote the following code for a function "prime_factors n" to return all the factors of n that are also prime.
prime_factors n = [x | x<-primes, n `mod` x == 0]
On executing prime_factors 12 it gives me the correct output [2,3 but keeps executing after that with no output. Why is this happening and how can I put a stop it?
For reference, here's the entire code segment:
primes :: [Integer]
primes = f [2..] where f (p:xs) = p: f [x | x <- xs, x mod p/=0] f [] = []
prime_factors n = [x | x<-primes, n mod x == 0, x*2 <= n]
primes :: Int -> [Integer]
primes n = take n $ f [2..]
where f (p:xs) = p: f [x | x <- xs, x `mod` p/=0]
prime_factors :: Int -> [Integer]
prime_factors n = [x | x<-primes n, n `mod` fromIntegral x == 0]
This is not a beautiful solution (am relatively new to Haskell myself), but it stops the program from running indefinitely by using the take function to ensure that you never get more entries than a finite number of entries up to n, which by definition will be far more than you need because there will always be fewer primes than natural numbers up to a given threshold, i.e., length [2,3] < length [1,2,3] etc.
Hopefully, someone else can give you a more elegant solution. But this one works.
I'm trying to learn haskell and implemented a function conseq that would return a list of consecutive elements of size n.
conseq :: Int -> [Int] -> [[Int]]
conseq n x
| n == length(x) = [x]
| n > length(x) = [x]
| otherwise = [take n x] ++ (conseq n (drop 1 x))
This works correctly.
> take 5 $ conseq 2 [1..10]
[[1,2],[2,3],[3,4],[4,5],[5,6]]
However, if I pass [1..] instead of [1..10], the program gets stuck in an infinite loop.
As I understood it, haskell has lazy evaluation so I should still be able to get the same result right? Is it length? Shouldn't the first two conditions evaluate to false as soon as the length becomes greater than n?
What did I misunderstand?
One of the main reasons why using length is not a good idea is because when it has to be evaluated on an infinite list, it will get stuck in an infinite loop.
The good news is however, we don't need length. It would also make the time complexity worse. We can work with two enumerators, one is n-1 places ahead of the other. If this enumerator reaches the end of the list, then we know that the first enumerator still has n-1 elements, and thus we can stop yielding values:
conseq :: Int -> [a] -> [[a]]
conseq n ys = go (drop (n-1) ys) ys
where go [] _ = []
go (_:as) ba#(~(_:bs)) = take n ba : go as bs
This gives us thus:
Prelude> conseq 3 [1 ..]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8,9],[8,9,10],[9,10,11],[10,11,12],[11,12,13],[12,13,14],[13,14,15],[14,15,16],[15,16,17],[16,17,18],[17,18,19],[18,19,20],[19,20,21],[20,21,22],[21,22,23],[22,23,24],[23,24,25],[24,25,26],[25,26,27],…
Prelude> conseq 3 [1 .. 4]
[[1,2,3],[2,3,4]]
The first thing your function does is calculate length(x), so it knows whether it should return [x], [x], or [take n x] ++ (conseq n (drop 1 x))
length counts the number of elements in the list - all the elements. If you ask for the length of an infinite list, it never finishes counting.
I wrote the following sieve:
isPrime :: Integer -> [Integer] -> Bool
isPrime n = all (\i -> n `mod` i /= 0)
sieve :: [Integer]
sieve = 2 : [i | i <- [3,5..], isPrime i sieve]
but I don't understand why it gets stuck after the first value. Running take 10 sieve results in [2, and nothing happens. It probably has something to do with infinite recursion. May the problem be that sieve is growing and at the same time it's used inside isPrime? For that reason I also tried modifying isPrime as follows, but without success:
isPrime :: Integer -> [Integer] -> Bool
isPrime n = all (\i -> n `mod` i /= 0) . takeWhile (<n)
EDIT: Surprisingly, #Jubobs's modification works:
isPrime :: Integer -> [Integer] -> Bool
isPrime n = all (\i -> n `mod` i /= 0) . takeWhile (\p -> p^2 <= n)
I cannot understand why this version of takeWhile works while the other does not. I see that with my previous version I tested many unnecessary divisors, but they were in a finite number nontheless.
The code should basically be equivalent to the following Python code:
def is_prime(n, ps):
for i in ps:
if n % i == 0: return False
return True
def sieve():
yield 2
n = 3
ps = [2]
while True:
if is_prime(n, ps):
yield n
ps.append(n)
n += 2
You cause an infinite recursion by applying all to the entire sieve and not just the values which you sieved so far. I.e. For the second element, isPrime tests all values in sieve instead of just 2.
In your Python version, you wrote
is_prime(n, ps)
which only tests n against all numbers sieved so far. The Python equivalent of what you did in Haskell is basically
is_prime(n, sieve())
Now, using takeWhile (<n) won't help because that also requires calculating the sieve elements. Imagine what happens for the second element of sieve (which should be 3): it tests all values of the sieve for which < 3 holds, but in order to test that you actually need to evaluate the sieve elements. So you still have an infinite recursion.
I'd say the comprehension list in sieve won't end until it completes, never. To use take like that, sieve would have to return the elements one by one. For instance, [1..] shows 1, 2 ,3 ,4... to infinity but your sieve only shows [2.
Or clearly not what I said
I'm currently stuck on setting upper limits in list comprehensions.
What I'm trying to do is to find all Fibonacci numbers below one million.
For this I had designed a rather simple recursive Fibonacci function
fib :: Int -> Integer
fib n
n == 0 = 0
n == 1 = 1
otherwise = fib (n-1) + fib (n-2)
The thing where I'm stuck on is defining the one million part. What I've got now is:
[ fib x | x <- [0..35], fib x < 1000000 ]
This because I know that the 35th number in the Fibonacci sequence is a high enough number.
However, what I'd like to have is to find that limit via a function and set it that way.
[ fib x | x <- [0..], fib x < 1000000 ]
This does give me the numbers, but it simply doesn't stop. It results in Haskell trying to find Fibonacci numbers below one million further in the sequence, which is rather fruitless.
Could anyone help me out with this? It'd be much appreciated!
The check fib x < 1000000 in the list comprehension filters away the fib x values that are less than 1000000; but the list comprehension has no way of knowing that greater values of x imply greater value of fib x and hence must continue until all x have been checked.
Use takeWhile instead:
takeWhile (< 1000000) [ fib x | x <- [0..35]]
A list comprehension is guaranteed to look at every element of the list. You want takeWhile :: (a -> Bool) -> [a] -> [a]. With it, your list is simply takeWhile (< 1000000) $ map fib [1..]. The takeWhile function simply returns the leading portion of the list which satisfies the given predicate; there's also a similar dropWhile function which drops the leading portion of the list which satisfies the given predicate, as well as span :: (a -> Bool) -> [a] -> ([a], [a]), which is just (takeWhile p xs, dropWhile p xs), and the similar break, which breaks the list in two when the predicate is true (and is equivalent to span (not . p). Thus, for instance:
takeWhile (< 3) [1,2,3,4,5,4,3,2,1] == [1,2]
dropWhile (< 3) [1,2,3,4,5,4,3,2,1] == [3,4,5,4,3,2,1]
span (< 3) [1,2,3,4,5,4,3,2,1] == ([1,2],[3,4,5,4,3,2,1])
break (> 3) [1,2,3,4,5,4,3,2,1] == ([1,2,3],[4,5,4,3,2,1])
It should be mentioned that for such a task the "canonical" (and faster) way is to define the numbers as an infinite stream, e.g.
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
takeWhile (<100) fibs
--[0,1,1,2,3,5,8,13,21,34,55,89]
The recursive definition may look scary (or even "magic") at first, but if you "think lazy", it will make sense.
A "loopy" (and in a sense more "imperative") way to define such an infinite list is:
fibs = map fst $ iterate (\(a,b) -> (b,a+b)) (0,1)
[Edit]
For an efficient direct calculation (without infinite list) you can use matrix multiplication:
fib n = second $ (0,1,1,1) ** n where
p ** 0 = (1,0,0,1)
p ** 1 = p
p ** n | even n = (p `x` p) ** (n `div` 2)
| otherwise = p `x` (p ** (n-1))
(a,b,c,d) `x` (q,r,s,t) = (a*q+b*s, a*r+b*t,c*q+d*s,c*r+d*t)
second (_,f,_,_) = f
(That was really fun to write, but I'm always grateful for suggestions)
The simplest thing I can think of is:
[ fib x | x <- [1..1000000] ]
Since fib n > n for all n > 3.