Разбор ошибки с моей функцией haskell, чтобы определить, является ли число простым - PullRequest
1 голос
/ 06 октября 2019

Я новичок в Haskell, и я не могу понять, что не так с моей функцией. Я получаю ошибку разбора и не понимаю, что не так с моим кодом.

isPrime :: Int -> Bool 
isPrime x
   | x <= 1 = False
   | x `mod` y == 0 for y in [2, 3 .. floor x^0.5] = False
   | otherwise = True

Ответы [ 2 ]

4 голосов
/ 06 октября 2019

Понимание списка в Haskell отличается от понимания в Python. Вместо expr for var in list это [expr | var <- list]. Кроме того, вам нужно all, чтобы убедиться, что все они верны. Далее, floor x^0.5 будет анализироваться как (floor x)^0.5, что вам не нужно. Используйте скобки, чтобы исправить это. Наконец, чтобы поднять что-то до нецелочисленной степени, вам нужно использовать ** вместо ^, но это создаст сложность, которую вы не хотите, поэтому просто используйте sqrt вместо.

2 голосов
/ 06 октября 2019

Условие x `mod` y == 0 for y in [2, 3 .. floor x^0.5] синтаксически недопустимо в Haskell. Например, в Haskell нет ключевого слова for. Более того, даже в Python вышеприведенное не будет работать, так как тогда вы создаете генератор .

. Вы можете использовать all :: Foldable f => (a -> Bool) -> f a -> Boolпроверить, не является ли x делимым на все значения в списке. Затем этот список является списком [ 2 .. &radic;x ].

Работа с (^) :: (Num a, Integral b) => a -> b -> a не будет работать, поскольку показатель степени должен иметь тип, который является членомкласс Integral. Если мы используем (**) :: Floating a => a -> a -> a, первый операнд должен иметь тип, который является членом класса типов Floating. Мы можем преобразовать Int s в Float, но это обычно не очень безопасно, поскольку возможны ошибки округления.

Поэтому может быть лучше использовать takeWhile :: (a -> Bool) -> [a] -> [a] для элементов, пока выполняется определенное условие. Таким образом, мы можем здесь проверить с помощью:

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

Таким образом, мы можем реализовать простую проверку как:

isPrime :: Int -> Bool
isPrime x
   | x <= 1 = False
   | otherwise = all ((/=) 0 . mod x) (takeWhile (\y -> y*y <= x) [2 .. ])
...