Haskell -列表推导中嵌套生成器的意外结果



在这个表达式中,x应该比n大1个单位。然而,结果列表大多是由负数组成的。

f :: [Integer]
f = [x-n | x <- [1,2..], n <- [0,1..]]

take 10 f输出:

[1,0,-1,-2,-3,-4,-5,-6,-7,-8]

我期望它是一个15的列表,我不确定为什么不是这样。

谢谢。

在您的定义中,对于x的每个值,n的每个值都与其配对。例如考虑

g :: [Integer]
g = [ (x, n) | x <- [1,2..4], n <- [0,1..3]]

输出为

[(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3),(3,0),(3,1),(3,2),(3,3),(4,0),(4,1),(4,2),(4,3)]

如果您希望xn的元素通过各自的位置配对,则尝试zip:

f1 = [x-n | (x, n) <- zip [1,2..] [0,1..]]
> take 10 f1
[1,1,1,1,1,1,1,1,1,1]

您给出的代码

f :: [Integer]
f = [x-n | x <- [1,2..], n <- [0,1..]]

是祈使句,相当于

for x in range(1, inf):
for n in range(0, inf):
return x - n

很明显,x一开始是1,然后循环n直到无穷大。所以你得到1 - 0,1 - 1,1 - 2等等。

从你的问题中,我猜你想要对每个列表中的元素逐一配对,而不是嵌套循环。因此,代码应该是

zipWith (-) [1..] [0..] -- this is equal to the infinite list [1,1,1,1,...]

正如@Willem Van Onsen在评论中提到的,你的理解相当于一个嵌套循环,其中x上的外部循环永远不会移动到下一次迭代。因此,对于每个n的值,您看到的是(1 - n)。

你似乎需要的是压缩两个列表在一起,然后做减法,像这样:

f = map (x -> (fst x) - snd x) $ zip [1,2..] [0,1..]

这将从每个列表中成对地获取元素,并进行减法,得到您期望的答案1。

相关内容

  • 没有找到相关文章

最新更新