Determining if a given number is a prime in haskell
Solution 1
A quick change to your code that will 'short circuit' the evaluation, and relies on the laziness of Haskell Lists, is:
isPrime k = if k > 1 then null [ x | x <- [2..k - 1], k `mod` x == 0] else False
The very first divisor of k
will cause the list to be non-empty, and the Haskell implementation of null
will only look at the first element of the list.
You should only need to check up to sqrt(k)
however:
isPrime k = if k > 1 then null [ x | x <- [2..isqrt k], k `mod` x == 0] else False
Of course, if you are looking to do high-performance primality testing, a library is preferred.
Solution 2
Here is the best resource for prime numbers in haskell in haskell.org
and here prime.hs github project
Solution 3
I like this approach:
First make function to get all factors of n:
factors n = [x | x <- [1..n], mod n x == 0]
Then check if factors are only the given number and 1, if so, the number is prime:
prime n = factors n == [1,n]
Solution 4
It's perhaps not directly relevant, but on the topic of finding primes in functional languages I found Melissa E. O'Neill's The Genuine Sieve of Eratosthenes very interesting.
Solution 5
Ignoring the primes issue, and focusing on the narrow point of a more efficient method of length xs == n
:
hasLength :: Integral count => [a] -> count -> Bool
_ `hasLength` n | n < 0 = False
[] `hasLength` n = n == 0
(_ : xs) `hasLength` n = xs `hasLength` (pred n)
isPrime k = [ x | x <- [2..k], k `mod` x == 0)] `hasLength` 1
Related videos on Youtube
devoured elysium
Updated on March 27, 2021Comments
-
devoured elysium about 3 years
So I have devised the following function for seeing if a given number is a prime in Haskell (it assumes the first prime is 2):
isPrime k = length [ x | x <- [2..k], k `mod` x == 0] == 1
it has the obvious pitfall of continuing the evaluation even if it is divisible by several numbers :(. Is there any sane way of "cutting" the evaluation when it finds more than one solution, using list comprehensions?
Also, which other implementations would you you try on? I'm not looking for performance here, I'm just trying to see if there are other more "haskellish" ways of doing the same thing.
-
Landei over 13 yearspossible duplicate of Lazy List of Prime Numbers
-
-
Will Ness over 4 years@Can your edit had broken this post. please don't do that.
-
Will Ness over 4 years@JamesKPolk thank you for rejecting a nonsensical edit on this post. :)
-
Can over 4 years@WillNess I re-checked my edit. Yet again I don't see how it deviates from the original answer. All of the information from the original author is preserved. As my edit note stated, it was just a minor formatting edit that fixed some wordings and styling.
-
Can over 4 years@WillNess It could be nonsensical to you but it wasn't for me, and certainly not for others as well since it also got approved by two others. All of the time, I edit posts on SE to make them more readable and approachable; and they get approved. These changes I've made could seem pointless to you but they're important indeed. Learning is crucial and information should be presented as best as it could.
-
Will Ness over 4 years@Can "yet again" (? it's our first communication that I know of.) two things you broke: 1. you changed
isqrt
tosqrt
which doesn't work with Integral types, so the code would cause an error. 2. you changed "relies" to "rely" which broke the meaning of the sentence (in a bit subtle, but still real, sense). -
Can over 4 years@WillNess Anyway, I don't care if you've reverted my edit. However, as a last statement, I would like to say that calling something that others have also supported nonsensical is both weird and more importantly rude. Make it a habit to first ask why.
-
Will Ness over 4 years@Can it is an unfortunate fact that your edit broke the post in two ways which I showed to you above, after you've asked. It is good to engage in a dialog, to clear things up. You shouldn't take personally the critique of an artifact, even if produced by you. See dreamsongs.com/10ideas.html for more about that.
-
Can over 4 years@WillNess rest assured, I'm definitely not taking it personally but just stating what I think. True, changing
isqrt
tosqrt
(hey, learned something new, thank you) was a mistake and I missed the wordrely
when I was typing fast but those weren't the only changes. Anyway, I really don't want to take this further. Thanks. -
Will Ness over 4 years@Can happy trails!
-
Jörg Brüggmann about 2 yearsFor a complete Haskell newbie not so bad. I tested it for some small numbers, and it worked. However, how does this work, anyway? Which factors does
factors
provide? It doesn't seem to be prime factors, nor all the factors. For instance the prime factors of8
are[2,2,2]
and the factors are[1, 2, 4, 8]
- but your function provides something different. The next question is whymap
- factors of factors? Please, if you don't mind than I would edit your post or please explain better. Thank you. -
Jörg Brüggmann about 2 yearsFactors can be evaluated by
factors n = [ n' | n' <- [1..n], n `mod` n' == 0]
-
Jörg Brüggmann about 2 yearsPrimes are numbers that just have 1 and the prime as factors and hence
isPrime n = factors n == [1,n]
. -
Jörg Brüggmann about 2 yearsThe code
factors n = [x | x <- [2..(n`div` 2)], mod n x == 0]
, andfactormap n = fmap factors $ factors n
,isMyNumberPrime n = case factormap n of [] -> True; _ -> False
does not work for1
. One is not a prime number, andisMyNumberPrime 1
evaluatesTrue
. -
DMJ almost 2 yearsThank you for your comment, Jorg. Unfortunately, it was so long ago that I posted the function that I've totally forgotten how it works (and much of Haskell, for that matter)