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

Jse*_*mol 6 haskell list infinite list-manipulation

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

实现这一目标最优雅的方式是什么?

我想出了这个解决方案:

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

但我相信必须有更好的方法.

Chr*_*tin 19

这似乎是理解的目的:

solution = 0 : [y | x <- [1..], y <- [x, -x]]
Run Code Online (Sandbox Code Playgroud)


Wil*_*sem 12

iterate

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

solution = iterate nxt 0
    where nxt i | i > 0 = -i
                | otherwise = 1-i
Run Code Online (Sandbox Code Playgroud)

或者我们可以用if- then- 来内联这个else:

solution = iterate (\i -> if i > 0 then -i else 1-i) 0
Run Code Online (Sandbox Code Playgroud)

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

solution = iterate (\i -> fromEnum (i < 1)-i) 0
Run Code Online (Sandbox Code Playgroud)

哪个更无瑕疵:

import Control.Monad(ap)

solution = iterate (ap subtract (fromEnum . (< 1))) 0
Run Code Online (Sandbox Code Playgroud)

(<**>)

我们也可以使用<**>来自应用程序的运算符来生成每次正数和负数变量的数字,如:

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

solution = 0 : ([1..] <**> [id, negate])
Run Code Online (Sandbox Code Playgroud)

  • 优秀使用Applicative! (2认同)
  • 你需要翻转版本,以便`id`和`negate`交替; `[id,negate] <*> [1 ..]`将`id`应用于另一个列表的每个元素,然后对它们应用`negate`.由于第二个列表是无限的,你永远不会得到负数.(更简单地说,`<**>`不仅仅是'flip <*>`.) (2认同)