简体   繁体   English

在Haskell中生成无限列表[0,1,-1,2,-2,...

[英]Produce the infinite list [0, 1, -1, 2, -2, … in Haskell

So suppose we want to produce the list [0, 1, -1, 2, -2, ... in Haskell. 因此,假设我们想在Haskell中生成列表[0, 1, -1, 2, -2, ...

What is the most elegant way of accomplishing this? 实现这一目标最优雅的方式是什么?

I came up with this solution: 我想出了这个解决方案:

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

But I am sure there must be a better way. 但我相信必须有更好的方法。

这似乎是理解的目的:

solution = 0 : [y | x <- [1..], y <- [x, -x]]

With iterate iterate

Perhaps a more elegant way to do this, is by using iterate :: (a -> a) -> a -> [a] with a function that generates each time the next item. 也许更优雅的方法是使用iterate :: (a -> a) -> a -> [a] ,其函数每次生成下一个项目。 For instance: 例如:

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

Or we can inline this with an if - then - else : 或者我们可以用if - then - else来内联这个:

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

Or we can convert the boolean to an integer, like @melpomene says, with fromEnum , and then use this to add 1 or 0 to the answer, so: 或者我们可以使用fromEnum将布尔值转换为整数,如@melpomene所说,然后使用fromEnum 10添加到答案中,这样:

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

Which is more pointfree: 哪个更无瑕疵:

import Control.Monad(ap)

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

With (<**>) (<**>)

We can also use the <**> operator from applicate to produce each time the positive and negative variant of a number, like: 我们也可以使用来自应用程序的<**>运算符来生成每次正数和负数变量的数字,如:

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

solution = 0 : ([1..] <**> [id, negate])

How about 怎么样

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

or 要么

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

?

How about: 怎么样:

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

On a moment's reflection, using nub instead of tail would be more elegant in my opinion. 在片刻的反思中,在我看来,使用nub而不是tail会更优雅。

another primitive solution 另一种原始解决方

alt = 0 : go 1
  where go n = n : -n : go (n+1)

You could also use concatMap instead of foldr here, and replace map negate [1..] with [0, -1..] : 你也可以在这里使用concatMap而不是foldr ,并用[0, -1..]替换map negate [1..] [0, -1..]

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

If you want to use negate instead, then this is another option: 如果你想使用negate ,那么这是另一种选择:

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

只是因为没人说:

0 : concatMap (\x -> [x,-x]) [1..]

迟到了,但这也会做到

solution = [ (1 - 2 * (n `mod` 2)) * (n `div` 2) | n <- [1 .. ] ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM