Reputation: 79
FINAL EDIT:
My final function is:
isPrime n = n > 1 && n < 4
|| n `mod` 2 /= 0
&& n `mod` 3 /= 0
&& length [x | x <- [5, 11..round (sqrt (fromIntegral n))], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
The issue was that I was trying to treat n
as both a Floating
in sqrt n
, and as an Integral
in n mod x
. So I had to do fromIntegral n
to force n to be treated as an Integral
and not as a Floating
.
Also I just screwed up some of my code.
So I have two functions:
primes = filterPrime [2..]
where filterPrime (p:xs) = p : filterPrime [x | x <- xs, x `mod` p /= 0]
above is straight off of haskell.org, an example being take 5 primes
results in [2,3,5,7,11]
My function isPrime
is the following:
isPrime n = isPrime n = n > 1 && n < 4
|| (n `mod` 2 == 0 || n `mod` 3 == 0)
&& length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
However, when I call isPrime
I get the error:
EulerMath.hs:6:33: error:
* No instance for (RealFrac Int) arising from a use of `round'
* In the expression: round (n ** 0.5)
In the expression: [5, 11 .. round (n ** 0.5)]
In a stmt of a list comprehension: x <- [5, 11 .. round (n ** 0.5)]
|
6 | && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
| ^^^^^^^^^^^^^^^^
EulerMath.hs:6:40: error:
* No instance for (Floating Int) arising from a use of `**'
* In the first argument of `round', namely `(n ** 0.5)'
In the expression: round (n ** 0.5)
In the expression: [5, 11 .. round (n ** 0.5)]
|
6 | && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
| ^^^^^^^^
EulerMath.hs:6:45: error:
* No instance for (Fractional Int) arising from the literal `0.5'
* In the second argument of `(**)', namely `0.5'
In the first argument of `round', namely `(n ** 0.5)'
In the expression: round (n ** 0.5)
|
6 | && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
| ^^^
I don't know how to annotate the isPrime
function correctly (read: I don't know how to annotate properly at all) so I don't get this error
Upvotes: 1
Views: 200
Reputation: 1375
The problem is, n ** 0.5
(or simply written as sqrt n
) requires n
to be Floating
:
(**) :: Floating a => a -> a -> a
sqrt :: Floating a => a -> a
But mod
requires n
to be Integral
:
mod :: Integral a => a -> a -> a
Haskell is a language, where there is no implicit type conversions, so you can't just pass an Int
to sqrt
. You can try it in GHCi:
x = 4 :: Int
sqrt x -- error
To solve that conflict you can use such a function fromIntegral :: (Integral a, Num b) => a -> b
that allows you to convert any Integral
type to any Num
type, and all Floating
types are Num
, so you will be able to use n
in sqrt
:
isPrime n = length [x | x <- take (round (sqrt (fromIntegral n))) primes, n `mod` x == 0] == 0
Also, we can simplify it a bit with $
application operator to omit some ()
and null
function to check whether the list is empty:
isPrime n = null [x | x <- take (round $ sqrt $ fromIntegral n) primes, n `mod` x == 0]
Try it there: https://repl.it/@Yuri12358/so-primes
Upvotes: 1
Reputation: 119877
Let's look at the types of tge involved operators.
(**) :: Floating a => a -> a -> a
mod :: Integral a => a -> a -> a
You apply both operators to the same variable n
. There is no type that satisfies both constraints however, and even if there where, Haskell wouldn't know how to choose one.
There are a couple of ways to solve this. One is to say fromIntegral n ** 0.5
(or, perhaps better, use sqrt
). Another one can be found here.
Last but not least you may want to notice that taking √n elements from a list of primes doesn't quite make sense. You want primes that are less than √n. Look at the takeWhile
function.
Upvotes: 1