1

我是 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
4

2 回答 2

4

Haskell 中的列表推导与 Python 中的不同。而不是expr for var in list,它是[expr | var <- list]。此外,您需要all验证它们都是真实的。此外,floor x^0.5将解析为(floor x)^0.5您不想要的。使用括号来修复它。最后,要将某些东西提高到非整数幂,您需要使用**而不是^,但这会引入您不想要的复杂性,所以只需使用sqrt

于 2019-10-06T14:33:23.873 回答
2

该条件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 .. √x ]

使用(^) :: (Num a, Integral b) => a -> b -> a将不起作用,因为指数应该是属于类型类成员的Integral类型。如果我们使用(**) :: Floating a => a -> a -> a第一个操作数,则该类型应该是类型类的成员Floating。我们可以将Ints 转换为 a Float,但这通常不是很安全,因为可能存在舍入错误。

因此takeWhile :: (a -> Bool) -> [a] -> [a],只要满足特定条件,使用 to 获取元素可能会更好。所以我们可以在这里检查:

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 .. ])
于 2019-10-06T14:56:12.893 回答