1

I am a beginner with Haskell and I can't seem to understand what is wrong with my function. I keep getting a parse error and I don't understand what is wrong with my code.

isPrime :: Int -> Bool 
isPrime x
   | x <= 1 = False
   | x `mod` y == 0 for y in [2, 3 .. floor x^0.5] = False
   | otherwise = True
Will Ness
  • 70,110
  • 9
  • 98
  • 181
aralk
  • 73
  • 6

2 Answers2

4

List comprehensions are different in Haskell than they are in Python. Instead of expr for var in list, it's [expr | var <- list]. Also, you need an all to make it verify they're all true. Further, floor x^0.5 will parse as (floor x)^0.5, which you don't want. Use parentheses to fix it. Finally, to raise something to a non-integer power, you need to use ** instead of ^, but this will introduce complexity you don't want, so just use sqrt instead.

2

The condition x `mod` y == 0 for y in [2, 3 .. floor x^0.5] is not syntactically valid in Haskell. Haskell for example has no for keyword. Furthermore even in Python the above would not work, since then you are constructing a generator.

You can make use of all :: Foldable f => (a -> Bool) -> f a -> Bool to check if x is not dividable by all values in a list. That list is then a list [ 2 .. √x ].

Working with (^) :: (Num a, Integral b) => a -> b -> a will not work, since the exponent should be of a type that is a member of the Integral typeclass. If we make use of (**) :: Floating a => a -> a -> a the first operand should be of a type that is a member of the Floating typeclass. We can convert Ints to a Float, but that is usually not very safe, since there can be rounding errors.

It therefore might be better to make use of takeWhile :: (a -> Bool) -> [a] -> [a] to take elements, as long as a certain condition holds. So we can here check with:

Prelude> takeWhile (\y -> y*y <= 20) [2 ..]
[2,3,4]

So we can implement the prime checker as:

isPrime :: Int -> Bool
isPrime x
   | x <= 1 = False
   | otherwise = all ((/=) 0 . mod x) (takeWhile (\y -> y*y <= x) [2 .. ])
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555