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.

我的问题是——

  • 我们可以在列表推导中使用“或”吗?
  • 如果没有,请告诉我如何以其他方式完成

我是函数式编程的新手,请帮助我。

4

4 回答 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]
于 2013-04-08T13:30:18.047 回答
8

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

您正在寻找的功能是|| :: Bool -> Bool -> Bool. 它接受两个布尔值,True如果其中一个是,则返回TrueFalse否则返回。

[x | x <- [1..10], x `mod` 5 == 0 || x `mod` 3 == 0]
于 2013-04-08T13:30:49.810 回答
2

你可以做这样的列表理解:

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

or函数适用于列表

于 2013-04-08T13:30:43.493 回答
0

事实上,我在or这里使用可能还不错:

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

...或者可能更具可读性...

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

不利的一面是它可能看起来有点吓人,但从好的方面来说,您可以通过这种方式轻松测试更多除数。

于 2013-04-09T06:45:42.413 回答