1) 问题在于它sqrt
具有 type (Floating a) => a -> a
,但您尝试使用 Integer 作为参数。因此,您必须首先将 Integer 转换为 Floating,例如通过编写sqrt (fromIntegral x)
2)我看不出为什么 == 不应该是惰性的,但是为了测试一个空集合,您可以使用该null
函数(这绝对是惰性的,因为它适用于无限列表):
isPrime :: Integer->Bool
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0]
但为了获得更惯用的解决方案,请将问题分解为更小的子问题。首先,我们需要 y*y <= x 的所有元素 y 的列表:
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..]
为了更加清楚,您可以“外包” lambda:
isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
您可以通过用 not $ any 替换 null $ filter 使其几乎“人类可读”:
isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x