gpt4 book ai didi

haskell - 经验丰富的 Haskell 开发人员如何在*设计*时应对懒惰问题?

转载 作者:行者123 更新时间:2023-12-03 07:19:41 24 4
gpt4 key购买 nike

我是一名中级 Haskell 程序员,在严格的 FP 和非 FP 语言方面拥有丰富的经验。我的大多数 Haskell 代码都分析中等大的数据集(10^6..10^9 的东西),所以懒惰总是潜伏着。我对 thunk、WHNF、模式匹配和共享有相当好的理解,并且我已经能够使用 bang 模式和 seq 修复泄漏,但这种分析和祈祷方法感觉肮脏和错误。

我想知道经验丰富的 Haskell 程序员如何在设计时处理懒惰问题。我不是在询问像 Data.ByteString.Lazy 或 Foldl' 这样的简单项目;相反,我想知道您如何看待导致运行时内存问题和棘手调试的低级惰性机制。

您如何看待设计时的 thunk、模式匹配和共享?

您使用哪些设计模式和习惯用法来避免泄漏?

您是如何学习这些模式和习语的,您有一些好的引用资料吗?

如何避免过早优化非泄漏非问题?

(时间预算于 2014 年 5 月 15 日修订):

您是否预算了大量的项目时间来查找和修复内存问题?

或者,您的设计技能通常会规避内存问题,并且您会在开发周期的早期就得到预期的内存消耗吗?

最佳答案

我认为大多数“严格性泄漏”问题的发生是因为人们没有一个好的概念模型。没有良好概念模型的 Haskeller 倾向于持有并传播“越严格越好”的迷信。也许这种直觉来自于他们玩弄小例子和紧密循环的结果。但这是不正确的。在正确的时间偷懒和在正确的时间严格同样重要。

数据类型有两个阵营,通常称为“data”和“codata”。尊重每个人的模式至关重要。

  • 产生“数据”(Int、ByteString、...)的操作必须强制靠近它们发生的位置。如果我向累加器添加一个数字,我会小心确保在添加另一个数字之前它会被强制执行。在这里,对惰性的良好理解非常重要,尤其是它的条件性质(即严格性命题不采用“X 被求值”的形式,而是“ Y 被求值时,也被求值” X“)。
  • 产生和消耗“codata”(列出大多数时间、树、大多数其他递归类型)的操作必须增量地进行。通常 codata -> codata 转换应该为它们消耗的每一位信息生成一些信息(模跳过如 filter )。 codata 的另一个重要部分是尽可能线性地使用它——即仅使用列表的尾部一次;树的每个分支只使用一次。这确保了 GC 可以在消耗碎片时收集它们。

当您拥有包含数据的 codata 时,需要特别小心。例如。 iterate (+1) 0 !! 1000在评估之前最终会生成一个大小为 1000 的 thunk。您需要再次考虑条件严格性——防止这种情况的方法是确保列表中的 cons 被消耗时,会添加其元素。 iterate违反了这一点,所以我们需要一个更好的版本。

iterate' :: (a -> a) -> a -> [a]
iterate' f x = x : (x `seq` iterate' f (f x))

当你开始编写东西时,当然很难判断什么时候会发生坏情况。一般来说,很难创建在 data 和 codata 上同样工作的高效数据结构/函数,重要的是要记住哪个是哪个(即使在不能保证的多态设置中,您也应该记住一个并尝试尊重它)。

分享是很棘手的,我想我主要是根据具体情况来处理它。因为它很棘手,所以我尝试保持其本地化,选择不向一般模块用户公开大型数据结构。这通常可以通过暴露组合器来生成有问题的东西,然后一次性生成和消耗它来完成(单子(monad)上的代码密度转换就是一个例子)。

我的设计目标是让每个函数都尊重我类型的数据/协同数据模式。我通常可以击中它(尽管有时需要深思熟虑——多年来这已经变得很自然),而且当我这样做时,我很少遇到泄漏问题。但我并不是说这很容易——它需要规范库和语言模式的经验。这些决定并不是孤立做出的,一切都必须同时正确才能顺利进行。一件调音不当的乐器可能会毁掉整个音乐会(这就是为什么“随机扰动优化”几乎无法解决此类问题)。

Apfelmus 的 Space Invariants文章有助于进一步发展您的空间/thunk 直觉。另请参阅下面 Edward Kmett 的评论。

关于haskell - 经验丰富的 Haskell 开发人员如何在*设计*时应对懒惰问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23280936/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com