You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell:如何在列表推导中更新无限列表的每个变量各一次

解决Haskell无限三元组列表的遍历顺序问题

嘿,这个问题我太懂了!你现在写的列表推导式会先把a和b死死固定在0,然后让c一路无限递增,自然就只会输出(0,0,0), (0,0,1), (0,0,2)...这种单调的序列。要改成你想要的那种每个变量都能逐步更新的模式,我们可以换个遍历思路——按三元组的最大元素来分组遍历,这样就能保证每个变量都有机会被更新,生成你要的[(0,0,0), (0,0,1), (0,1,1), (1,1,1), ...]序列。

直接上修改后的代码:

list1 = [(a,b,c) | n <- [0..], a <- [0..n], b <- [a..n], c <- [b..n]]

为什么这个写法管用?

我们拆解一下逻辑:

  • 首先遍历n从0开始递增,n代表当前三元组中允许的最大元素;
  • 对于每个n,先选a从0到n;
  • 再选b从a到n,保证b不小于a;
  • 最后选c从b到n,保证c不小于b;

这样生成的序列完全符合你的要求:

  • 当n=0时:只有(0,0,0);
  • 当n=1时:依次生成(0,0,1), (0,1,1), (1,1,1);
  • 当n=2时:会生成(0,0,2), (0,1,2), (0,2,2), (1,1,2), (1,2,2), (2,2,2);
    以此类推,每个变量都会随着n的递增逐步更新,不会再出现单一变量无限循环的情况。

如果你想要的是另一种按元素总和分组的遍历方式(比如先输出所有和为0的三元组,再和为1的,以此类推),也可以用这个写法:

list1 = [(a,b,c) | s <- [0..], a <- [0..s], b <- [0..s-a], let c = s - a - b]

不过这个生成的序列开头是(0,0,0), (0,0,1), (0,1,0), (1,0,0)...,和你给出的示例不太匹配,所以第一种写法更贴合你的需求。

内容的提问来源于stack exchange,提问作者mellow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:24:31