[英]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]]
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
1
或0
添加到答案中,这样:
solution = iterate (\i -> fromEnum (i < 1)-i) 0
Which is more pointfree: 哪个更无瑕疵:
import Control.Monad(ap)
solution = iterate (ap subtract (fromEnum . (< 1))) 0
(<**>)
(<**>)
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.