13

我听说有一个 GHC 分支默认编译成严格的代码,而惰性可以通过注释来启用。(IIRC,他说一家金融公司开发分支并将其用于生产代码。)这是真的吗?我找不到它。

该人士还建议,严格评估比惰性评估(默认情况下)更实用的观点越来越得到认可。我在 Haskell 邮件列表中没有发现这一点,但也许那是因为那里的人不注重实践?

我在严格的 Haskell 上找到的只是明确的东西,比如$!and rnf。虽然我发现惰性求值非常优雅,但我想在 Haskell 中开发一个程序,我想在其中避免空间泄漏并希望获得可预测的性能。

免责声明:我不是在为严格辩护,我只是想看看严格的 Haskell 或类似的东西。

4

5 回答 5

12

你在找门徒

所以在 Haskell 中有两种懒惰需要区分。有惰性 I/O,这是一种可憎的东西,可以通过 iteratee 库解决(无耻插件:包括我的管道库)。然后是纯计算中的惰性,这仍然存在争议,但我将尝试总结惰性的主要优点,因为您已经熟悉缺点:

懒惰更有效

一个简单的例子是:

any = foldr (||) False

any查找列表中的任何值是否为True. 这只会评估直到 first 的元素True,因此列表是否很长并不重要。

惰性只计算它必须的量,这意味着如果你将两个惰性计算链接在一起,它实际上可以提高结果计算的时间复杂度。 这个 Stack Overflow 评论给出了另一个很好的例子。

这实际上是 iteratee 库非常节省资源的原因。他们只做尽可能多的工作来生成结果,这导致非常有效的内存和磁盘使用以及非常易于使用的语义。

懒惰本质上更具可组合性

使用严格语言和函数式编程的人都知道这一点,但实际上我在开发库时无意中证明了这一点pipes,其中惰性版本是唯一允许Category实例的版本。管道实际上可以在任何 monad 中工作,包括纯Identitymonad,所以我的证明也可以转化为纯代码。

这就是为什么我相信一般的惰性确实是编程的未来的真正原因,但是我仍然认为 Haskell 是否“正确”地实现了惰性是一个悬而未决的问题。

于 2012-05-28T14:29:14.330 回答
5

听起来您好像听说过 Robert Ennals关于GHC投机性评估的博士论文。他创建了 GHC 的一个分支,称为“spec_eval”分支,其中进行了推测评估。因为 Haskell 是非严格的,而不是显式的惰性,所以 spec_eval严格到它实际有所作为的程度。虽然它在所有情况下都更快,但它需要对 GHC 进行大量更改并且从未合并。

这个问题之前已经在这个网站上回答过。

于 2012-11-29T01:09:07.063 回答
3

关于为什么你不应该回避 Haskell 的懒惰,已经说了一些好话,但我觉得最初的问题仍未得到解答。

Haskell 中的函数应用是非严格的;也就是说,仅在需要时才评估函数参数。

~ Haskell 报告 2010 > 预定义类型和类 # 严格评估

然而,这有点误导。实现可以在需要之前评估函数参数,但仅限于有限的范围。您必须保留非严格语义:因此,如果参数的表达式导致无限循环,并且未使用该参数,则使用该参数的函数调用不得无限循环。

因此,您可以以不完全“懒惰”的方式实现 Haskell,但它也不能是“严格”的。乍一看,这似乎是一个矛盾,但事实并非如此。您可能想要查看的一些相关主题:

  • Eager Haskell,Haskell 编程语言的一种实现,默认情况下使用渴望评估。我相信这就是您所想的(尽管它不是 GHC 的一个分支)。
  • 推测执行和推测并行(参见例如推测包)。
  • Optimistic Evaluation,SPJ 的一篇关于通过严格优化加速 GHC 的论文。
于 2012-05-29T08:27:26.120 回答
3

我听说有一个 GHC 分支默认编译成严格的代码,而懒惰可以通过注释来启用

您可以尝试 GHC 8.0.2、8.2.2 或 8.4.1,也就是最后三个版本中的任何一个。他们有一个{-# LANGUAGE Strict #-}用于数字代码等的编译指示。

金融公司开发分支并将其用于生产代码。)这是真的吗?我找不到它。

渣打银行确实开发了自己的 Haskell 编译器。我不希望他们向公众提供它。我不确定默认情况下它是否严格。

该人士还提出了严格评估比懒惰评估更实用的观点

这没有意义,也没有证据支持。事实上,llvm-hs-pure 包通过选择使用 state monad 的严格版本而不是惰性版本引入了一个错误。此外,类似parallel-io包之类的东西也不起作用。

我想在 Haskell 中开发一个程序,我想避免空间泄漏并希望具有可预测的性能。

这两年我没有被懒惰导致的空间泄漏咬伤。我建议改为使用基准测试并分析您的应用程序。编写具有可预测性能的 Haskell 比添加严格注释并希望您的程序仍然可以编译更容易。理解你的程序、分析和学习函数式数据结构比盲目地添加编译器编译指示来提高程序的性能会更好。

于 2018-04-08T21:08:07.830 回答
2

如果我理解正确的话,严格的 Haskell 不可能有我们所知道的单子 I/O。Haskell 中的想法是所有 Haskell 代码都是纯代码(包括 IO 操作,其工作方式与 State monad 类似),并且“main”为运行时提供 IO () 类型的值,然后反复强制排序运算符 >>= .

对于 Tekmo 的帖子,您可以查看 Robert Harper 的博客,* http://existentialtype.wordpress.com/2011/04/24/the-real-point-of-laziness/ 和相关的。它是双向的。

以我的经验,一开始懒惰是很困难的,但你习惯了它就很好了。

懒惰的经典倡导文章是 Hughes 的论文“为什么函数式编程很重要”,您应该可以轻松找到它。

于 2012-05-28T17:34:48.720 回答