我正在查找Haskell中的程序,该程序测试给定数字是否为素数。
prime :: (Integral a) => a -> Bool
prime 1 = True
prime x = and [ x `mod` y /= 0 | y <- [2..(x-1)] ]
我不明白这个and
的目的是什么:prime x = and [
。
答案 0 :(得分:3)
虽然这个问题已经得到解答,但请允许我添加一些内容:
在检查and
的来源时,您会得到:
and :: [Bool] -> Bool
and = foldr (&&) True
首先要注意的是and
获取布尔变量列表,并返回单个布尔变量,并且表达式x mod y /= 0
的计算结果为True或False(因此符合[Bool]要求)。
更重要的是要注意foldr
是一个懒惰的折叠。因此,这里的惰性折叠是最佳的,因为&&
是一个半严格的运算符。因此,与半严格算子组合的惰性折叠将在遇到False
的第一次出现时产生短路评估。因此,在实际非素数的情况下,and
将避免评估整个列表,从而节省您的时间。不要相信我的话,如果你愿意,可以定义你自己严格的and
版本(使用更严格的foldl
):
andStrict :: [Bool] -> Bool
andStrict x = foldl (&&) True
primeStrict :: (Integral a) => a -> Bool
primeStrict x = andStrict [x `mod` y /= 0 | y <- [2..(x-1)]]
现在运行:
prime 2000000000
注意那是怎么回事?现在这样做,但在它崩溃你的内存堆栈之前打断它:
primeStrict 2000000000
这显然比较慢,你可以打断它。这是and
的作用,这就是为什么and
是用foldr
编写的,因此为什么会为您发布的示例代码选择它。希望这有助于作为支持性答案。
答案 1 :(得分:2)
and
对列表的所有元素执行逻辑和操作。
Primes只能被一个人和他们自己整除;这意味着只要在2和x
之间存在除数(没有余数),该数字就不是素数。
列表推导生成一个布尔值列表,对应于您的x
是否可被上述范围内的数字整除。
一旦它们中的任何一个是假的(一个除数为零的除法),这个数字就不是素数。
考虑:
x = 7
[7 % 2 /= 0 -> True, 7 % 3 /= -> True, ...]
-- now applying and
True && True && ... && True evaluates to True
and
可以表示为可以在列表上执行的更一般的操作 - 使用逻辑和的 fold 。例如:and' = foldr (&&) True
。
答案 2 :(得分:2)
表达式
[x `mod` y /= 0 | y <- [2..(x - 1)]
是Bool
的列表,因为mod x y /= 0
(由于反引号格式化而带有前缀表示法)返回Bool
。 and
函数只对列表中的每个元素进行逻辑AND,所以
and [True, False] == False
and [True, True] == True