How is a recursive prime number checker written in Haskell? - haskell

I'm very new to Haskell (and functional programming in general), and I'm trying some basic exercises to try to get an understanding of the language. I'm writing a "naive" prime number checker that divides each number under the input to check if there is any remainder. The only constructs I've learned so far are comprehension lists and recursive functions, so I'm constrained to that. Here's what I'm trying:
isprime 1 = False
isprime 2 = True
isprime n = isprimerec n (n-1)
isprimerec _ 1 = False
isprimerec n t = if (n `rem` t) == 0 then False else isprimerec n (n-1)
The intention is that the user would use isprime n. Then isprime would use isprimerec to determine if the number is prime. It's a pretty round-about way of doing it, but I don't know any other way with my limited knowledge of Haskell.
Here's what happens when I try this:
isprimerec 10 9
Runs forever. I have to use Ctrl+C to stop it.
isprimerec 10 5
Returns False. The else part is never evaluated, so the function never calls itself.
I'm not sure why this is happening. Also, is this anywhere near close to how a Haskell programmer would approach this problem? (And I don't mean checking primality, I know this isn't the way to do it. I'm just doing it this way as an exercise).

The problem is in this line
isprimerec n t = if (n `rem` t) == 0 then False else isprimerec n (n-1)
You use (n - 1) as the second argument where it should be (t - 1). A further point, I think you want the isprimerec _ 1 case = True.
As to your more general question of whether or not this is idiomatic, I think you're on the right track. ghci has a decent command line debugger. I found this by putting your code in a file, loading it, and then issuing the command :break isprimerec. I then called your function and stepped through it with :step.

Your bug is a simple typo; at the end of isprimerec, your second parameter becomes n-1 instead of t-1. But that aside, the function isn't quite idiomatic. Here's the first pass of how I would write it:
isPrime :: (Ord a, Integral a) => a -> Bool
isPrime n | abs n <= 1 = False
isPrime 2 = True
isPrime n = go $ abs n - 1
where go 1 = False
go t = (n `rem` t /= 0) && go (t-1)
(I might call go something like checkDivisors, but go is idiomatic for a loop.) Note that this exposes the bug in your code: once go is local to isPrime, you don't need to pass n around, and so it becomes clearer that recursing on it is incorrect. The changes I made were, in rough order of importance:
I made isprimerec a local function. Nobody else would need to call it, and we lose the extra parameter.
I made the function total. There's no reason to fail on 0, and not really any reason to fail for negative numbers. (Technically speaking, p is prime if and only if -p is prime.)
I added a type signature. It's a good habit to get into. Using Integer -> Bool, or even Int -> Bool, would also have been reasonable.
I switched to interCaps instead of alllowercase. Just formatting, but it's customary.
Except I'd probably make things terser. Manual recursion is usually unnecessary in Haskell, and if we get rid of that entirely, your bug becomes impossible. Your function checks that all the numbers from 2 to n-1 don't divide n, so we can express that directly:
isPrime :: (Ord a, Integral a) => a -> Bool
isPrime n | abs n <= 1 = False
| otherwise = all ((/= 0) . (n `rem`)) [2 .. abs n - 1]
You could write this on one line as
isPrime :: (Ord a, Integral a) => a -> Bool
isPrime n = abs n > 1 && all ((/= 0) . (n `rem`)) [2 .. abs n - 1]
but I wouldn't be surprised to see either of these last two implementations. And as I said, the nice thing about these implementations is that your typo isn't possible to make in these representations: the t is hidden inside the definition of all, and so you can't accidentally give it the wrong value.

Your else branch is broken since it calls isprimerec n (n-1) every time. You probably ought to write isprimerec n (t-1) instead to have it count down.
You could also use a higher-order function all to make this a lot simpler.
isprime 1 = False
isprime n = all (\t -> n `rem` t /= 0) [2..(n-1)]

So OK, you've got the two bugs: your
isprimerec _ 1 = False
isprimerec n t = if (n `rem` t) == 0 then False else isprimerec n (n-1)
should have been
isprimerec _ 1 = True
isprimerec n t = if (n `rem` t) == 0 then False else isprimerec n (t-1)
or, with list comprehension,
isprime n = n>1 && and [ rem n t /= 0 | t <- [n-1,n-2..2] ]
(Internalize that extra parameter t, it was a technicality anyway! -- A-ha, but what's that and, you ask? It's just like this recursive function, foldr (&&) True :: [Bool] -> Bool.)
But now a major algorithmic drawback becomes visually apparent: we test in the wrong order. It will be faster if we test in ascending order:
isprime n = n>1 && and [ rem n t /= 0 | t <- [2..n-1] ]
or even much faster yet if we stop at the sqrt,
isprime n = n>1 && and [ rem n t /= 0 | t <- [2..q] ]
where q = floor (sqrt (fromIntegral n))
or test only by odds, after the 2 (why test by 6, if we've tested by 2 already?):
isprime n = n>1 && and [ rem n t /= 0 | t <- 2:[3,5..q] ]
where q = floor (sqrt (fromIntegral n))
or just by primes (why test by 9, if we've tested by 3 already?):
isprime n = n>1 && and [ rem n t /= 0 | t <- takeWhile ((<= n).(^2)) primes ]
primes = 2 : filter isprime [3..]
And why test the evens when filtering the primes through - isn't it better to not generate them in the first place?
primes = 2 : filter isprime [3,5..]
But isprime always tests division by 2 -- yet we feed it only the odd numbers; so,
primes = 2 : 3 : filter (noDivs (drop 1 primes)) [5,7..]
noDivs factors n = and [ rem n t /= 0 | t <- takeWhile ((<= n).(^2)) factors ]
And why generate the multiples of 3 (i.e. [9,15 ..] == map (3*) [3,5..]), only to test and remove them later? --
{- [5,7..]
== [j+i | i<-[0,2..], j<-[5]] -- loop unrolling, 3x:
== [j+i | i<-[0,6..], j<-[5,7,9]]
== 5:[j+i | i<-[0,6..], j<-[7,9,11]]
== 5:[7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43, ...
\\ [ 9, 15, 21, 27, 33, 39, ...
== [j+i | i<-[0,6..], j<-[ 9 ]]
-}
primes = 2:3:5: filter (noDivs (drop 2 primes))
[j+i | i<-[0,6..], j<-[7, 11]]
We can skip over the multiples of 5 in advance as well (as another step in the Euler's sieve, euler (x:xs) = x : euler (xs `minus` map (x*) (x:xs))):
-- [j+i | i<-[0, 6..], j<-[7, 11]] -- loop unrolling, 5x:
-- == 7:[j+i | i<-[0,30..], j<-[11,13,17,19,23,25,29,31,35,37]]
-- \\ [j+i | i<-[0,30..], j<-[ 25, 35 ]]
primes = 2:3:5:7: filter (noDivs (drop 3 primes))
[j+i | i<-[0,30..], j<-[11,13,17,19,23, 29,31, 37]]
... but that's already going far enough, for now.

Related

How can I make this prime check function more succinct in Haskell?

So I spent the last hour or so trying to write up an effecient haskell function that checks if a number is prime or not. I came up with this algorithm that I'm rather happy with:
prime :: Int -> Bool
prime x
| x == 1 = False
| x == 2 = True
| x == 3 = True
| x `mod` 2 == 0 = False
| x `mod` 3 == 0 = False
| otherwise = all (\y -> x `mod` y /= 0) $ dividends x
where
dividends z =
takeWhile ((<=) . floor . sqrt . fromIntegral $ z)
$ concatMap (\x -> [x-1, x+1]) [6 * x | x <- [1..]]
I also uploaded a notebook that checks the run time of the algorithm and compares it to the sieve method in case anyone is interested that is here: https://anaconda.org/freemo/primes/notebook
My question is, as someone new to haskell how can I make this algorithm more idomatic. I have a feeling the anonymous functions I used can be eliminated, and there are probably other ways I can make it more concise without having a negative effect on the run time. How can I write this in an more idiomatic haskell way?
The thing I'd consider most unidiomatic here are the equality comparisons. In Haskell, we generally prefer pattern matching, which you can directly apply to the first three cases:
prime 1 = False
prime 2 = True
prime 3 = True
prime x
| ...
(The difference is cosmetic in this example, but often pattern matching makes code much safer, more succinct and sometimes also significantly more performant.)
Next, you're using both a list comprehension and concatMap. Both constructs do largely the same thing, and are equivalent to monadic binds. But a) it's usually benefitial to use only one of these syntaxes in a place, b) monad is actually stronger than necessary: applicative will do as well, and can be written quite nicely here.
import Control.Applicative
...
(6*) <$> [1..] <**> [pred, succ]
Then, I find this ((<=) . floor . sqrt . fromIntegral $ z) awkward. More natural would be in flipped form:
takeWhile (>= floor (sqrt $ fromIntegral z)) ...
...but generally speaking, better yet is to avoid the square root entirely:
takeWhile ((>=z) . (^2)) ...
The reason being, square-root is pretty expensive and has floating-point inaccuracies, so it's often better to square the other side of the equation instead. Unfortunately, this is actually not reliable here, because the squaring might lead to Int overflows, and Integer would make the performance probably worse than with float-sqrt, because it's done for every element of the list rather than just once. So, a square-root is actually sensible here.
The dividends function is actually superfluous since you only ever call it with x as the argument. (It might be argued that it's sensible to still give this a name, but at any rate you don't need to give it an argument.)
The predicate for the all is something I would consider making point-free.
Final version would then be:
prime :: Int -> Bool
prime 1 = False
prime 2 = True
prime 3 = True
prime x
| x `mod` 2 == 0 = False
| x `mod` 3 == 0 = False
| otherwise = all ((/= 0) . (x`mod`))
. takeWhile (>= floor (sqrt $ fromIntegral x))
$ (6*) <$> [1..]
<**> [pred, succ]
So I modified #leftaroundabout 's answer slightly and am using this. Just putting it up here in case anyone winds up using it.
import Control.Applicative
prime'' :: Int -> Bool
prime'' 1 = False
prime'' 2 = True
prime'' 3 = True
prime'' x
| x `mod` 2 == 0 = False
| x `mod` 3 == 0 = False
| otherwise = all
-- check if x is not divisibile by the divisors
((/= 0) . (x `mod`))
-- only take divisors less than or equal to sqrt(x)
. takeWhile (<=(floor . sqrt . fromIntegral $ x))
-- generate divisors as an infinite list 6n +/- 1
$ [6,12..] <**> [(-1+), (1+)]

Determine a prime number with right fold

I found this solution on the internet and I need some help understanding it:
isPrime' :: Integer -> Bool
isPrime' n = foldr (\x acc -> (n `rem` x) /= 0 && acc) True primes
where primes = 2 : filter isPrime' [3,5..]
A couple of things:
My understanding is that if the accumulator for a fold function is a Boolean it has to be set in the lambda function itself. Something like:
(\x acc -> if (n `rem` x /= 0) then False else acc) True primes
But here it is not the case.
Also, the range being used for primes does not have a terminating number. I know the reason this works is because of Haskell's lazy evaluation, but how exactly is that working here?
Lastly, this function does not seem like it would return the proper Boolean. A prime number is one that has no other divisors but itself and 1. So shouldnt the lambda read:
(\x acc -> if (n `rem` x) == 0 then False else acc) True primes
I am thoroughly confused. Please help me out.
At least for me, your code doesn't finish. It is missing the stop condition, which can be seen in a similar solution from the wiki:
isPrime n = n > 1 &&
foldr (\p r -> p*p > n || ((n `rem` p) /= 0 && r)) True primes
primes = 2 : filter isPrime [3,5..]
Here you can see, that the condition p*p > n produces True, when there is no possible prime factor left. Because of lazy execution the right part of || is not evaluated and the foldr stops.
having
primes = [p1, p2, p3, ..., pn, ...]
calculating
isPrime' n = foldr (\x acc -> (n `rem` x) /= 0 && acc) True primes
is as if calculating
isPrime' n = rem n p1 /= 0 && (
rem n p2 /= 0 && (
rem n p3 /= 0 && (
..........
rem n pk /= 0 && (
.......... ..... ))))
For composite ns this works – one of the rem expressions will be 0, the inequality is false, and the whole expression is false too, because && is short-circuiting, lazy in its 2nd argument.
For prime ns this will cause a problem: none of the rem expressions will be 0, by definition of a prime, until we reach a prime p_i == n itself among the primes. But it's not there yet, as we haven't detected it as being prime yet - we're just doing it right now. To test whether it is prime, we must know that it is prime - clearly a bad situation.
A value will be demanded from primes which is not there yet. This is known as "black hole". It causes an error, and calculation aborts (or becomes stuck).
To put it differently, it is as if the definition
primes = 2 : filter isPrime' [3,5..]
were defined as
primes = 2 : [ n | n <- [3,5..]
, and [rem n p /= 0 | p <- takeWhile (< n) primes]]
The problem is that to stop when n is prime, takeWhile (< n) must reach a prime p above or equal to n in primes, but it's not there yet. "Black hole".
The famous "sieve" code gets around this problem by "transposing" the workflow,
primes = map head . iterate (\(x:xs)-> filter ((/=0).(`rem`x)) xs) $ [2..]
thus making it work while retaining its computational inefficiency (the lesser problem of your code), testing its candidates by too many primes needlessly (where each prime is tested by all its preceding primes instead of just those not above its square root), making it unnecessarily slow.
This is mitigated by putting a properly early stop to the testing, with
primes = 2 : [ n | n <- [3,5..]
, and [rem n p /= 0 | p <- takeWhile ((<= n).(^2)) primes]]
which, back in terms of your definition, is equivalent to
isPrime' n = p1*p1 > n || rem n p1 /= 0 && (
p2*p2 > n || rem n p2 /= 0 && (
p3*p3 > n || rem n p3 /= 0 && (
..........
pk*pk > n || rem n pk /= 0 && (
.......... ..... ))))
You can write this down as a foldr-based definition now (which can be seen in another answer here).
The expression
(n `rem` x) /= 0
clearly produces a Bool result. The parameter acc is already a Bool value. So
(n `rem` x) /= 0 && acc
is a logical-AND of two Bool values, which clearly produces a Bool result. Where is the confusion?
The input list is infinite, consisting only of odd numbers. So long as you can produce a result after examining only a finite number of values, laziness makes everything fine.

Expressing recursion in Haskell - Prime numbers sequence

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 (:).

Haskell Prime-testing confusion

So I'm totally new to Haskell, hope it doesn't show too much. By any means, I was trying to create a function to determine if a number is prime. The basic idea is this: Given a number, see if it is divisible by any other number less than it. If so, return false. If not, it's prime, return true. The code so far (that is known to be working) is this:
divisible :: Integer -> Integer -> Bool
divisible x 2 = even x
divisible x y = ((x `mod` y) /= 0) && not (divisible x (y-1))
isPrime :: Integer -> Bool
isPrime x = not (even x) && not (divisible x (x-1))
Produces:
ghci> isPrime 9
False
ghci> isPrime 13
True
What I'd like to do is optimize this a bit, since I only need to check values less than or equal to sqrt(x). The problem is, when I try and implement this, stuff gets crazy:
isPrime x = not (even x) && not (divisible x (ceiling(sqrt(fromIntegral(x-1)))))
Besides the fact that it looks terrible (I said I was new), it doesn't give the correct result:
ghci> isPrime 9
False
ghci> isPrime 13
False
I'm trying to figure out what changed, because:
ghci> ceiling(sqrt(13))
4
Seems to be giving me the correct number. I know this is a small problem, but I'm seriously confused...
You got your conditions mixed up:
divisible x y = ((x `mod` y) /= 0) && not (divisible x (y-1))
should be
divisible x y = (x `mod` y) == 0 || divisible x (y-1)
for the test to work.
As is, your divisible function expands e.g.
divisible 21 5 = (21 `mod` 5 /= 0) && not (divisible 21 4)
= (21 `mod` 5 /= 0) && not ((21 `mod` 4 /= 0) && not (divisible 21 3))
= not ((21 `mod` 4 /= 0) && not ((21 `mod` 3 /= 0) && not (divisible 21 2)))
= not (True && not (False && not (divisible 21 3)))
= not (not False)
= False
since 21 `mod` 3 == 0, and isPrime 21 evaluates to True with the square root bound.
However, I get
*StrangePrime> isPrime 9
True
*StrangePrime> isPrime 13
True
with your code using the square root.
Without the square root, it happened to work for odd numbers, because the difference between an odd composite and any of its divisors is always even. Unfolding divisible a few steps for n = p*m, where p is the smallest prime factor of the odd composite n, we see
divisible n (n-1) = n `mod` (n-1) /= 0 && not (divisible n (n-2))
= not (divisible n (n-2))
= not (n `mod` (n-2) /= 0 && not (divisible n (n-3)))
= not (not (divisible n (n-3)))
= not^2 (divisible n (n-3))
and inductively
divisible n (n-1) = not^(k-1) (divisible n (n-k))
if there are no divisors of n larger than n-k. Now, in the above situation, the largest divisor of n is m = n - (p-1)*m, so we obtain
divisible n (n-1) = not^((p-1)*m-1) (divisible n m)
= not^((p-1)*m-1) (n `mod` m /= 0 && not (...))
But n `mod` m == 0, so we have
divisible n (n-1) = not^((p-1)*m-1) False
Since p is odd, p-1 is even, and hence so is (p-1)*m, so altogether we have an odd number of nots, which is the same as one not, giving
divisible n (n-1) = True
isPrime n = not (even n) && not (divisible n (n-1)) = True && not True = False
If p is an odd prime, the unfolding reaches divisible p (p-1) = not^(p-3) (divisible p (p - (p-2))). p-3 is even, divisible p 2 is even p, which is False.
Generally, consider divisible n s for an odd n, and let d be the largest divisor of n not exceeding s, if n is composite, or d = 2 if n is prime. The unfolding of divisible n s still proceeds the same way
divisible n s = not^k (divisible n (s-k))
while no divisor has been found and s-k > 2. So in the case of a composite n, we find
divisible n s = not^(s-d) (divisible n d)
= not^(s-d) (n `mod` d /= 0 && not (...))
= not^(s-d) False
= odd (s-d)
= even s -- since d is odd, as a divisor of an odd number
and in the case of an odd prime n,
divisible n s = not^(s-2) (divisible n 2)
= not^(s-2) (even n)
= not^(s-2) False
= odd s
So divisible n s measures the parity of the distance of s to the next smaller divisor of n or to 2, whichever is larger. When s was n-1, the starting point was always even, so it worked out correctly, but ceiling (sqrt (fromIntegral (n-1))) can be odd, in which case the results are flipped and composites are declared prime and vice versa.
You can make your divisible function work for the primality test of odd numbers with a square root bound if you make sure that the first call gets an even second argument (so if ceiling (sqrt (fromIntegral (n-1))) is odd, start at ceiling (sqrt (fromIntegral (n-1))) + 1), but the logic of that function is confusing, and its name doesn't correctly describe its results.
A more idiomatic way to write it would be
isPrime n = and [n `mod` k /= 0 | k <- [2 .. ceiling (sqrt $ fromIntegral n)]]
The test becomes more efficient when one skips candidate divisors that are already known to be nondivisors from prior tests, easy is skipping all even numbers except 2,
isPrime 2 = True
isPrime n = all ((/= 0) . (n `mod`)) (2 : [3, 5 .. ceiling (sqrt (fromIntegral n))])
slightly more involved, but still more efficient is also skipping multiples of 3
isPrime n = all ((/= 0) . (n `mod`)) (takeWhile (<= bound) (2:3:scanl (+) 5 (cycle [2,4])))
where
bound = ceiling (sqrt (fromIntegral (n-1)))
In the same vein one can eliminate the multiples of more small primes from the trial divisors, each gaining a bit of efficiency, but at the cost of a more complicated wheel, e.g. also eliminating multiples of 5 leads to
isPrime n = all ((/= 0) . (n `mod`)) (takeWhile (<= bound) (2:3:5: scanl (+) 7 (cycle [4,2,4,2,4,6,2,6])))
where
bound = ceiling (sqrt (fromIntegral (n-1)))
Here's how I'd do it:
divisibleBy :: (Integral a) => a -> a -> Bool
divisibleBy x y = mod x y == 0
isPrime :: (Integral a) => a -> Bool
isPrime x = or $ map (divisibleBy x) [2..(x-1)]
divisibleBy is a simple test of divisibility. isPrime performs this test on all integers between 1 and x, returning true if x is divisible by any of those integers. You might change the upper bound to root x, as you've done in your code, but otherwise this works.

Haskell prime test

I'm new to Haskell, and I'm trying a bit:
isPrime :: Integer->Bool
isPrime x = ([] == [y | y<-[2..floor (sqrt x)], mod x y == 0])
I have a few questions.
Why when I try to load the .hs, WinHugs say: Instances of (Floating Integer, RealFrac Integer) required for definition of isPrime?
When the interpreter finds one element in the right set, it immediately stops or it computes all the set? I think you know what I mean.
Sorry about my english.
1) The problem is that sqrt has the type (Floating a) => a -> a, but you try to use an Integer as argument. So you have to convert your Integer first to a Floating, e.g. by writing sqrt (fromIntegral x)
2) I see no reason why == shouldn't be lazy, but for testing for an empty collection you can use the null function (which is definitely lazy, as it works on infinite lists):
isPrime :: Integer->Bool
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0]
But in order to get an more idiomatic solution, break the problem into smaller sub-problems. First, we need a list of all elements y with y*y <= x:
takeWhile (\y -> y*y <= x) [2..]
Then we need only the elements that divide x:
filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..])
Then we need to check if that list is empty:
isPrime x = null (filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..]))
And if this looks to lispy to you, replace some of the parens with $
isPrime x = null $ filter (\y -> x `mod` y == 0) $ takeWhile (\y -> y*y <= x) [2..]
For additional clarity you can "outsource" the lambdas:
isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
You can make it almost "human readable" by replacing null $ filter with not $ any:
isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
Because sqrt has the type Floating a => a -> a. This means the input has to be a Floating type and the output will be the same type. In other words x needs to be a Floating type. However you declared x to be of type Integer, which is not a Floating type. In addition floor needs a RealFrac type, so x needs to be that as well.
The error message suggests that you fix that by making Integer a Floating type (by defining an instance Floating Integer (and the same for RealFrac).
Of course this is not the correct approach in this case. Rather you should use fromIntegral to convert x to a Real (which is an instance of Floating and RealFrac) and then give that to sqrt.
Yes. As soon as == sees that the right operand has at least one element, it knows it is not equal to [] and thus returns False.
That being said, null is a more idiomatic way to check whether a list is empty than [] ==.
Regarding the second point, it stops, for example:
[] == [x | x <- [1..]]
Returns False
Landei's solution is great, however, if you want a more efficient¹ implementation we have (thanks to BMeph):
-- list of all primes
primes :: [Integer]
primes = sieve (2 : 3 : possible [1..]) where
sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]
possible (x:xs) = 6*x-1 : 6*x+1 : possible xs
isPrime :: Integer -> Bool
isPrime n = shortCircuit || (not $ any divisible $ takeWhile inRangeOf primes) where
shortCircuit = elem n [2,3] || (n < 25 && ((n-1) `mod` 6 == 0 || (n+1) `mod` 6 == 0))
divisible y = n `mod` y == 0
inRangeOf y = y * y <= n
The 'efficiency' comes from the use of constant primes. It improves the search in two ways:
The Haskell runtime could cache the results so subsequent invocations are not evaluated
It eliminates a range of numbers by logic
note that the sieve value is simply a recursive table, where says the head of
the list is prime, and adds it to it. For the rest of the lists if there is no
other value already in the list that composes the number then its also prime
possible is list of all possible primes, since all possible primes are in the
form 6*k-1 or 6*k-1 except 2 and 3
The same rule is applied for shortCircuit too to quickly bail out of calculations
Footnote by D.F.
¹ It's still a terribly inefficient way to find primes. Don't use trial division if you need primes larger than a few thousand, use a sieve instead. There are several far more efficient implementations on hackage.
I think WinHugs needs to import a module for Integer and etc... Try Int
The interpreter will not compute anything until you call e.g. isPrime 32 then it will lazily compute the expression.
PS your isPrime implementation is not the best implementation!

Resources