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