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

filter与takeWhile差异及运行时问题:GHCI执行效率差异原因探究

为什么两个Haskell表达式执行差异这么大?

这问题问得挺有意思的,我来给你拆解清楚哈!

首先得先搞懂两个表达式的核心区别,还有Haskell惰性求值的特性在这儿起的关键作用:

第一个表达式:快速返回的原因

我们看这段代码:

sum (takeWhile (<10000) (filter odd (map (^2) [1..])))

这里的核心是takeWhile (<10000)函数——它的逻辑是:从输入列表里逐个取元素,一旦遇到第一个不满足<10000的元素,就立刻停止生成后续所有元素。

我们算一下平方数:100的平方是10000,刚好是第一个不满足<10000的数。所以前面的奇数平方数到99²=9801就截止了,整个被处理的列表是有限的,sum自然能快速算出结果(也就是你看到的166650)。

第二个表达式:永远跑不完的原因

再看这段代码:

sum (filter (<10000) (filter odd (map (^2) [1..])))

这里用的是filter (<10000),filter的逻辑和takeWhile完全不同:它会遍历整个输入列表,把所有满足条件的元素筛选出来。但问题在于,它的输入是map (^2) [1..]——这是一个无限列表(从1开始的所有整数的平方)。

虽然后面的平方数(比如100²、101²……)都远大于10000,filter会把它们全部过滤掉,但filter不知道“后面再也不会有满足条件的元素了”,它会一直不停地生成下一个平方数、检查是否是奇数、再检查是否小于10000,永远停不下来。

这里要澄清:这不是无限循环,而是在遍历一个无限列表,永远到不了头,所以你等了10秒只能手动中断。

核心差异总结

  • takeWhile是“遇到不符合条件的就停”,能把无限列表截断成有限列表,所以可以快速完成计算。
  • filter是“遍历整个列表找符合条件的”,面对无限列表时会一直遍历下去,永远无法终止计算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:26:40