Haskell列表理解有两个变量

时间:2012-07-09 17:34:32

标签: haskell list-comprehension

我试图找到一些特殊数字,这样当它除以2得1时,除以3得2,依此类推至6。

这完美有效。

[ x | x <- [1..1000],x `mod` 2 == 1 , x `mod` 3 == 2 , x `mod` 4 == 3 , x `mod` 5 == 4 , x `mod` 6 == 5]
答:

[59,119,179,239,299,359,419,479,539,599,659,719,779,839,899,959]

我试图让它变得更好,以便它不会太冗长,但以下不起作用。

[ x | x <- [1..1000], y <- [2..6], x `mod` y == (y-1) ]

所有x的y 任何满足条件,但我想要的是,我想要x满足 all y的条件。

3 个答案:

答案 0 :(得分:3)

列表理解很短,但经常模糊不清。编写/读取monadic代码通常更容易。让我们翻译第一个版本

do
x <- [1..1000] -- here a value is selected
guard $ x `mod` 2 == 1  -- it checked
guard $ x `mod` 3 == 2 -- and checked
guard $ x `mod` 4 == 3 
guard $ x `mod` 5 == 4 
guard $ x `mod` 6 == 5 -- you got the point
return x -- value returned

,第二个是

do
x <- [1..1000] -- value selected
y <- [2..6]  -- another value selected
guard $ x `mod` y == (y-1) -- the pair of previously selected values is checked 
return x -- and now the first value returned.

===

第二次写得正确:

do
x <- [1..1000]
guard $ and $ do
              y <- [2..6] 
              return $ x `mod` y == 1
return x

它可以通过多种方式重写,包括

[x | x <- [1..1000], and [x `mod` y == 1 | y <- [2..6] ] ]

答案 1 :(得分:2)

您可以将条件写为

[ x | x <- [1..1000], all (\y -> x `mod` y == y-1) [2 .. 6]]

但是你可以在这个具体案例中做得更好,

let modulus = foldl1 lcm [2 .. 6]
[x | x <- [1 .. 1000], x `mod` modulus == modulus - 1]
[modulus - 1, 2*modulus - 1 .. 1000]  -- even better

答案 2 :(得分:2)

只是为了记录,您仍然可以从第二次尝试中“恢复”解决方案:

import Data.List

map head $ filter ((==5).length) $ group [ x | x <- [1..1000], y <- [2..6], x `mod` y == (y-1) ]