简体   繁体   中英

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.

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

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. 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 :

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:

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.

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..] :

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

If you want to use negate instead, then this is another option:

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 .. ] ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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