1) Проблема в том, что sqrt
имеет тип (Floating a) => a -> a
, но вы пытаетесь использовать Integer в качестве аргумента. Таким образом, вы должны сначала преобразовать ваше целое число в число с плавающей точкой, например, написав sqrt (fromIntegral x)
2) Я не вижу причин, по которым == не должно быть ленивым, но для тестирования пустой коллекции вы можете использовать функцию null
(которая определенно ленива, поскольку она работает с бесконечными списками):
isPrime :: Integer->Bool
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0]
Но чтобы получить более идиоматическое решение, разбейте проблему на более мелкие подзадачи. Во-первых, нам нужен список всех элементов y с y * y <= x: </p>
takeWhile (\y -> y*y <= x) [2..]
Тогда нам нужны только элементы, которые делят x:
filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..])
Затем нам нужно проверить, пуст ли этот список:
isPrime x = null (filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..]))
И если вам это не нравится, замените некоторые из паренов на $
isPrime x = null $ filter (\y -> x `mod` y == 0) $ takeWhile (\y -> y*y <= x) [2..]
Для большей ясности вы можете "отдать" лямбды на аутсорсинг:
isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
Вы можете сделать его почти "читабельным для человека", заменив нулевой $ filter на not $ any:
isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x