1

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

Lemma
  • 59
  • 6
  • To annotate you add a line: `isPrime :: Int -> Bool`. – Micha Wiedenmann Dec 04 '19 at 09:05
  • There are purely integer algorithms to find the floor of the square root of an integer. See [here](https://en.wikipedia.org/wiki/Integer_square_root) for example. So you can avoid dealing with floating point numbers entirely. – jpmarinier Dec 04 '19 at 09:42

2 Answers2

1

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.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Yeah I don't know why I was doing the take primes. I was mixing my primes function with the function from [the 6k + 1 test](https://en.wikipedia.org/wiki/Primality_test#Pseudocode). That was just an oopsie doopsie. I edited the code to use `sqrt n` and I edited the code to use `round (sqrt n)` and both still result in the error for `Floating Int`. – Lemma Dec 04 '19 at 08:17
  • You cannot take a square root of an integer. Have you looked at fromIntegral? – n. m. could be an AI Dec 04 '19 at 08:24
  • I just edited to be `round (sqrt (fromIntegral n))` thanks to you and Yuri and it worked perfectly. Thank you so much – Lemma Dec 04 '19 at 08:29
1

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

Yuri Kovalenko
  • 1,325
  • 9
  • 19
  • I just edited to be `round (sqrt (fromIntegral n))` thanks to you and n. 'pronouns' m.and it worked perfectly. Thank you so much – Lemma Dec 04 '19 at 08:30