haskell - 在 Haskell 中,在此列表理解中使用 takeWhile 或使用 "regular"不等式有什么区别?

标签 haskell functional-programming lazy-evaluation

我正在努力学习 Haskell(为了伟大的利益),而我正在做的许多不同的事情之一就是尝试解决一些欧拉计划问题,同时我正在测试我的勇气。

在做一些基于斐波那契的问题时,我偶然发现并开始尝试斐波那契序列的递归无限列表版本:

fibs = 1 : 2 : zipWith (+) fibs (tail fibs)

对于其中一个 PE 问题,我需要提取小于 4,000,000 的斐波那契数的子序列。我决定通过列表理解来做到这一点,在我玩弄代码时,我偶然发现了一些我不太理解的东西;我假设是我对 Haskell 的惰性求值方案的掌握不够,导致事情变得复杂。

以下理解效果很好:

[x | x <- takeWhile (<= 4000000) fibs, even x]

下一个理解永远旋转;所以我经历了并将输出返回到标准输出,虽然它停在正确的位置,但它似乎只是永远继续评估递归定义的列表,而不会在达到上限值后完成;表明列表中的最后一项以逗号打印,但不存在其他列表项或右方括号:

[x | x <- fibs, x <= 4000000, even x]

那么,能够很好地处理无限列表的各种函数所使用的 secret 武器到底是什么?

最佳答案

函数takeWhile不断获取输入列表的元素,直到到达第一个不满足谓词的元素,然后停止。只要至少有一个元素不满足谓词,takeWhile 就会将无限列表转换为有限列表。

你的第一个表情是这样的

Keep taking elements of this infinite list until you find one greater than 4,000,000 and then stop. Include each element in the output if it's even.

第二个表达式表示

Keep taking elements of this infinite list. Include each element in the output if it's less than or equal 4,000,000 and it's even.

当您观察到永远挂起的输出时,该函数正在忙于生成更多斐波那契数并检查它们是否小于或等于 4,000,000。它们都不是,这就是为什么没有任何内容打印到屏幕上,但该函数无法知道它不会在列表中进一步遇到一个小数字,因此它必须继续检查。

关于haskell - 在 Haskell 中,在此列表理解中使用 takeWhile 或使用 "regular"不等式有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13347430/

相关文章:

haskell - 为什么多态类型同义词不像实例中的多态数据声明那样工作?

javascript - 如何在 Javascript 中实现可靠、通用且类型安全的函数?

functional-programming - 学习函数式编程的一个好的用例是什么?

haskell - 将惰性字节串与另一个字节串分割

r - 如何在 dplyr 中进行功能重命名?

亚马逊上的 Haskell (Yesod)

python - GtkOverlay 隐藏 GtkTextView

Haskell:if-then-else block 和具有非对称构造函数的数据

haskell - 为什么 ghc 8.8.4 无法编译 ghci 可以加载的文件?

arrays - 查找数组元素的所有唯一组合的最佳方法?