7

所以假设我们想[0, 1, -1, 2, -2, ...在 Haskell 中生成列表。

完成此任务的最优雅方法是什么?

我想出了这个解决方案:

solution = [0] ++ foldr (\(a,b) c->a:b:c) [] zip [1..] $ map negate [1..]

但我相信一定有更好的方法。

4

8 回答 8

20

这似乎是理解的目的:

solution = 0 : [y | x <- [1..], y <- [x, -x]]
于 2018-01-06T17:34:09.007 回答
12

iterate

也许更优雅的方法是使用iterate :: (a -> a) -> a -> [a]每次生成下一个项目的函数。例如:

solution = iterate nxt 0
    where nxt i | i > 0 = -i
                | otherwise = 1-i

或者我们可以用if- then-内联它else

solution = iterate (\i -> if i > 0 then -i else 1-i) 0

或者我们可以将布尔值转换为整数,就像@melpomene 说的那样,使用fromEnum,然后使用它来添加10答案,所以:

solution = iterate (\i -> fromEnum (i < 1)-i) 0

哪个更无意义:

import Control.Monad(ap)

solution = iterate (ap subtract (fromEnum . (< 1))) 0

(<**>)

我们还可以使用 apply 中的<**>运算符来生成一个数字的正负变量,例如:

import Control.Applicative((<**>))

solution = 0 : ([1..] <**> [id, negate])
于 2018-01-06T17:34:22.333 回答
4

怎么样

concat (zipWith (\x y -> [x, y]) [0, -1 ..] [1 ..])

或者

concat (transpose [[0, -1 ..], [1 ..]])

?

于 2018-01-06T17:34:18.163 回答
4

怎么样:

tail $ [0..] >>= \x -> [x, -x]

在我看来,使用nub而不是tail会更优雅。

于 2018-01-06T17:43:35.820 回答
4

另一种原始解决方案

alt = 0 : go 1
  where go n = n : -n : go (n+1)
于 2018-01-07T03:17:03.733 回答
2

您也可以使用concatMap代替foldr此处,并替换map negate [1..][0, -1..]

solution = concatMap (\(a, b) -> [a, b]) $ zip [0, -1..] [1..]

如果您想negate改用,那么这是另一种选择:

solution = concatMap (\(a, b) -> [a, b]) $ (zip . map negate) [0, 1..] [1..]
于 2018-01-06T18:05:07.207 回答
1

只是因为没有人说:

0 : concatMap (\x -> [x,-x]) [1..]
于 2018-01-08T03:44:26.767 回答
0

聚会迟到了,但这也可以

solution = [ (1 - 2 * (n `mod` 2)) * (n `div` 2) | n <- [1 .. ] ]
于 2018-01-07T14:21:47.130 回答