I'm trying to define an is_prime function in Haskell. Can anyone point out the issue with the use of the any function?
In addition, I know that the below code is naïve, but I am learning the language so starting with babysteps.
is_prime 0 = False
is_prime 1 = False
is_prime 2 = True
is_prime n = any [n `mod` k == 0 | k <- [2.. sqrt n]]
Type of any is (a -> Bool) -> [a] -> Bool, so it accepts a predicate and a collection. So you should rewrite your last case as for instance
is_prime n = not $ any (\k -> n `mod` k /= 0)
[2 .. ceiling $ sqrt $ fromIntegral n]
fromIntegral is necessary because sqrt's type is Floating a => a -> a while your n is an integer. Subsequently, without ceiling the second argument of any would be Floating t => [t]. This would break, as calling mod, whose type is Integral a => a -> a -> a, on non-integral types is illegal.
If you'd like to look for some other implementations, I can recommend for example this discussion.
The accepted answer is, to my mind, incorrect as the is_prime function actually returns False if n is a prime, and here's why.
any function data returns True as soon as it encounters such an element in data that function data is True.
\k -> mod n k /= 0 returns True if applied to a number that does not divide some constant n.
thus, any returns True if there is a number in the given list that does not divide the number n we want to check for primality and False if there is one.
so, is_prime returns True for any number that is divisible by any number in the list [2 .. ceiling $ sqrt $ fromIntegral n], for example, 4 which clearly is not a prime.
With that said, the correct solution should look like this:
is_prime n = not $ any (\k -> n `mod` k == 0) [2 .. ceiling $ sqrt $ fromIntegral n]
This is because a number n is prime if it's not a multiple of any number between 2 and sqrt n.
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
I'm new to Haskell and have a question about types, it error out because it couldn't match expected type. I believe squarePrime is a bool, correct me if i'm wrong and it is complaining because it wants a int? Can someone explain, thanks in advance.
squarePrimes n = [n^2 | (n) <- [2..n-1], (all (\a -> mod n a /= 0) [2..n-1])]
multiOfFive a = mod a 5 == 0
fun n = [n | n <-[1..n], multiOfFive || squarePrimes n]
The 'squarePrimes n' function returns a list of Integers, as opposed to a Bool or a list of Bools. Looking at the list comprehension:
[n^2 | (n) <- [2..n-1], (all (\a -> mod n a /= 0) [2..n-1])]
This will produce a list of n^2, of n pulled from the range [2..n-1], for every n that satisfies the condition:
(all (\a -> mod n a /= 0) [2..n-1])
Then, in the list comprehension used in the definition of 'fun':
[n | n <-[1..n], multiOfFive || squarePrimes n]
A list is being constructed of each n in the range 1 to n, as long as the following condition is true:
multiOfFive || squarePrimes n
Haskell is expecting this to evaluate to a Bool. However, 'multiOfFive' is being called without any argument, and 'squarePrimes n' returns a list of Integers, as opposed to a Bool.
Without knowing exactly what the intention of 'fun n' is, I have altered the provided code a little bit to get a list comprehension that loads without error:
fun n = [n | n <- [1..n], (multiOfFive n) || (elem n (squarePrimes n))]
Now, it uses the 'elem' function to check whether a given 'n' is an element of the list 'squarePrimes n'.
I believe squarePrimes is a Bool, correct me if I'm wrong
GHCi will tell you:
λ> let squarePrimes n = [n^2 | (n) <- [2..n-1], (all (\a -> mod n a /= 0) [2..n-1])]
λ> :t squarePrimes
squarePrimes :: Integral a => a -> [a]
It is complaining because it wants an int? Can someone explain
Here Integral i => i is any integer type. That could for example be Int or Integer. This is because the integer literals 0, 1, 2 and the arithmetic operators you use aren't restricted to a specific integer type.
You're using squarePrimes n as a Bool.
You're also using multiOfFive as a Bool when its type is:
λ> let multiOfFive a = mod a 5 == 0
λ> :t multiOfFive
multiOfFive :: Integral a => a -> Bool
so a function that takes an integer type and returns a Bool.
My goal is to write a function that calculates the maximum Collatz number below a certain number 'n'. (It's a Project Euler question for those who are familiar.)
Some context: A Collatz number for a given integer is equal to the length of the Collatz sequence for that integer. A Collatz sequence for an integer is calculated as follows: the first number ("n0") in the sequence is that integer itself; if n0 is even, the next number in the sequence ("n1") is equal to n / 2; if n0 is odd, then n1 is equal to 3 * n0 + 1. We continue recursively extending the sequence until we arrive at 1, at which point the sequence is finished. For example, the collatz sequence for 5 is: {5, 16, 8, 4, 2, 1} (because 16 = 3 * 5 + 1, 8 = 16 / 2, 4 = 8 / 2,...)
I'm trying to write a function ("maxCollatzUnder") which, when passed an integer "m", returns the integer (less than or equal to m) which has the longest Collatz sequence (i.e., largest Collatz number). For example, maxCollatz 20 (i.e., what integer below (inclusive) 20 has the longest collage sequence?) should return 19 (the number 19 has a Collatz sequence of length 21: [19,58,29,88,44,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]).
In the code below, the "collatz" and "collatzHelper" functions compile and run correctly. I'm having trouble with the "maxCollatzUnder" function. This function intends to (I) create a list of 2-tuples (x,y) for each integer x ranging from 1 to m (where m is the function argument) and where where y represents the Collatz number for integer x and then (II) look through the list for the highest Collatz number (i.e., y) and return its associated integer (i.e., x)
maxCollatzUnder n = foldl(\acc (i,j) -> if j > acc then i else acc) 0
(zip [1..n] ( map collatzLength [1..n]))
where collatzLength n = length . collatz $ n
collatz n = map truncate $ collatzHelper n
collatzHelper 0 = [0]
collatzHelper 1 = [1]
collatzHelper n
| (truncate n) `mod` 2 == 0 = [n] ++ collatzHelper (n/2)
| otherwise = [n] ++ collatzHelper (3*n+1)
I get the following error when I (attempt to) compile.
*Main> :l PE14Collatz.hs
[1 of 1] Compiling Main ( PE14Collatz.hs, interpreted )
PE14Collatz.hs:7:89:
No instance for (RealFrac Int)
arising from a use of `collatzLength'
In the first argument of `map', namely `collatzLength'
In the second argument of `zip', namely
`(map collatzLength [1 .. n])'
In the third argument of `foldl', namely
`(zip [1 .. n] (map collatzLength [1 .. n]))'
Failed, modules loaded: none.
What's curious is that the code compiles and runs correctly if I change the "maxCollatzUnder" to the following code (see below). The only change is that, in the version below, the fold function returns "j" (i.e., the largest Collatz number) instead of "i" (i.e., the integer which generates the largest Collatz number).
maxCollatzUnder n = foldl(\acc (i,j) -> if j > acc then j else acc) 0
(zip [1..n] ( map collatzLength [1..n]))
where collatzLength n = length . collatz $ n
Suggestions on a more efficient/elegant approach are welcome though I would still be interested in understanding the cause of this error.
Because of your use of truncate (a method of RealFrac) and / (a method of Fractional, a superclass of RealFrac), Haskell infers the following two type signatures for your last two functions:
collatz :: (RealFrac a, Integral b) => a -> [b]
collatzHelper :: RealFrac a => a -> [a]
Haskell then tries to deduce the type of maxCollatzUnder, and its thought process goes like this:
"In collatzLength n = length . collatz $ n, we're passing n to collatz, so the argument to collatzLength must be a RealFrac."
"Therefore, in map collatzLength [1..n], [1..n] must be a list of RealFrac values."
"Therefore, the n in map collatzLength [1..n] must be a RealFrac type."
"Therefore, the n in zip [1..n] (which is the same n) must be a RealFrac type, and so [1..n] is a list of RealFracs."
"Therefore, the i in (\acc (i,j) -> if j > acc then i else acc) must be a RealFrac."
"Because the aforementioned lambda can return either i or acc, they must be the same type."
"Because j is being compared to acc, j must be the same type as acc — and thus the same type as i and a RealFrac."
"But wait— j is the return value from collatzLength, which is the return value of a call to length, and so it has to be an Int, but Int isn't in RealFrac!"
"ERROR! ERROR!"
I have to go now (the Compiler Cabal doesn't like me giving away their secrets), but the shortest fix is to not use truncate and / and just use div for (floored) integer division.
I want to list all integers that divide n. This is a homework question. So far I have done this.
divisors :: Int -> [Int]
divisors n | n < 1 = []
| otherwise = filter (\n -> n `mod` x == 0) [1..n]
where x = [1..n]
I know this is wrong, but I am not getting the right filter predicate. I don't know how the syntax is for doing this. and ofcourse I cannot use n mod n since that is just lists all elements 1 to n.
You want to check if mod n k == 0 for each k from 1 to n. The n is fixed (the argument of divisors) and the k varies, i.e. that is what should be the argument of the lambda expression
| otherwise = filter (\k -> n `mod` k == 0) [1 .. n]
I don't know what you are trying to do, but the type of mod is
mod :: Integral a => a -> a -> a
You call it with an Integral argument and a list of integral arguments.
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!