在列表推导式中使用 or

4

我正在尝试取出1到10之间可以被5或3整除的所有数字。
这是我目前的代码 -

giveList = 
[ x
 | x <- [1..10] ,
 (x `mod` 5 == 0) or (x `mod` 3 == 0)
]

然后我在ghci中加载函数。但是它给了我一个错误 -

> [1 of 1] Compiling Main             ( problem1.hs, interpreted )

problem1.hs:4:10:
    The function `x `mod` 5 == 0' is applied to two arguments,
    but its type `Bool' has none
    In the expression: (x `mod` 5 == 0) or (x `mod` 3 == 0)
    In a stmt of a list comprehension:
      (x `mod` 5 == 0) or (x `mod` 3 == 0)
    In the expression:
      [x | x <- [1 .. 10], (x `mod` 5 == 0) or (x `mod` 3 == 0)]
Failed, modules loaded: none.

我的问题是 -

  • 在列表推导式中,我们能使用 'or' 吗?
  • 如果不行,请告诉我其他方法

我刚接触函数式编程,请帮帮我。


无论如何,“or”都不会成为中缀运算符。你必须写成“`or`”! - AJF
4个回答

13
你可以在列表推导式中使用 or,但是
Prelude> :t or
or :: [Bool] -> Bool

那不是你在那个地方需要的函数,它是用于检查列表中是否存在任何一个元素为True的函数。你需要的是

(||) :: Bool -> Bool -> Bool

如果你想使用一个由字母组成的中缀函数名称,你需要用反引号括起来,就像你用mod一样,但是由于or只接受一个参数,你不能将该函数应用为中缀。
正确的列表版本应该是:
giveList = [ x | x <- [1 .. 10], x `mod` 5 == 0 || x `mod` 3 == 0]

谢谢,函数式编程对我来说似乎很奇怪。我将在大约7分钟内接受答案为正确。 - svineet
10
不比C语言更奇怪,因为它使用完全相同的运算符。 - Gabriella Gonzalez
@GabrielGonzalez,我在谈论函数式编程,而不是运算符。 - svineet

8

or 的类型签名为 or :: [Bool] -> Bool。它接受一个布尔值列表,并返回True,如果其中任何一个是True,否则返回False

你要找的函数是|| :: Bool -> Bool -> Bool。它接受两个布尔值,并返回True,如果其中任意一个是True,否则返回False

[x | x <- [1..10], x `mod` 5 == 0 || x `mod` 3 == 0]

2
您可以这样进行列表推导式:
[x | x <- [1..10], ((x `mod` 3) == 0) || ((x `mod` 5) == 0)]

or函数适用于列表


0
事实上,在这里使用or可能并不那么糟糕:
[x | x <- [1..10], or $ map ((==0).(x `mod`)) [3,5]]

......或者更易读的方式......

[x | x <- [1..10], any (==0) $ map (x `mod`) [3,5]]

缺点是它可能看起来有点吓人,但好处是你可以很容易地通过这种方式测试更多的除数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接