我听说有一个GHC的分支默认编译为严格的代码,而懒惰可以通过注释启用。 (IIRC,他说一家金融公司开发分支并将其用于生产代码。)这是真的吗?我找不到了。
该人士还表示,严格评估比懒惰评估(默认情况下)更实用的观点越来越受到人们的认可。 我没有在Haskell邮件列表中找到这个确认,但也许那是因为那里的人不是那种以实践为导向的?
我在严格的Haskell上找到的所有内容都是$!
和rnf
等明确的内容。虽然我发现惰性评估非常优雅,但我想在Haskell中开发一个程序,我希望避免空间泄漏,并希望获得可预测的性能。
免责声明:我不是要严格要求,我只想看看严格的Haskell或类似的东西。
答案 0 :(得分:11)
您正在寻找Disciple。
因此在Haskell中有两种懒惰可以区分。有懒惰的I / O,这是令人厌恶的,并且由iteratee库解决(无耻插件:包括我的pipes库)。然后是纯粹的计算中的懒惰,这仍然有待讨论,但我会尝试总结懒惰的关键优势,因为你已经熟悉了这个缺点:
懒惰效率更高
一个简单的例子是:
any = foldr (||) False
any
查找列表中的任何值是True
。这只会评估第一个True
之前的元素,因此列表很长也无关紧要。
懒惰只计算它的含量,这意味着如果你将两个惰性计算链接在一起,它实际上可以提高结果计算的时间复杂度。 This Stack Overflow comment给出了另一个很好的例子。
这实际上与iteratee库非常节省资源的原因相同。他们只需要完成与生成结果一样多的工作,这会导致非常高效的内存和磁盘使用,并且具有非常易于使用的语义。
懒惰本来就更具有组合性
对于那些使用严格和函数语言进行编程的人来说,这是众所周知的,但实际上我在pipes
库中无意间证明了这一点,其中懒惰版本是唯一允许的版本一个Category
个实例。管道实际上可以在任何monad中工作,包括纯Identity
monad,所以我的证明也转换为纯代码。
这就是为什么我认为一般的懒惰确实是编程的未来的真正原因,但是我仍然认为Haskell是否实现了“正确”的懒惰是一个悬而未决的问题。
答案 1 :(得分:4)
听起来你已经听说过Robert Ennals'PhD thesis on speculative evaluation和GHC。他创建了一个名为“spec_eval”分支的GHC分支,在那里进行了投机评估。因为Haskell是非严格的而不是明确的惰性,spec_eval 是严格到实际产生差异的程度。虽然它在所有情况下都更快,但它需要对GHC进行大量更改,并且从未合并过。
此问题在此网站上有been answered before种。
答案 2 :(得分:3)
为什么你不应回避Haskell的懒惰,已经说了些好话,但我觉得原来的问题仍然没有答案。
Haskell中的函数应用程序是非严格的;也就是说,仅在需要时才评估函数参数。
〜Haskell Report 2010 > Predefined Types and Classes # Strict Evaluation
然而,这有点误导。实现可以在需要之前评估函数参数,但仅限于有限的范围。您必须保留非严格语义:因此,如果参数的表达式导致无限循环,并且未使用该参数,则使用该参数的函数调用不得无限循环。
所以你 允许以一种不完全“懒惰”的方式实现Haskell,但它仍然不能“严格”。这似乎是乍一看的矛盾,但事实并非如此。您可能想要查看的一些相关主题:
答案 3 :(得分:3)
我听说有一个GHC分支默认编译为严格代码,而懒惰可以通过注释启用
您可以尝试GHC 8.0.2,8.2.2或8.4.1,也就是最后三个版本中的任何一个。它们有一个{-# LANGUAGE Strict #-}
pragma用于数字代码等。
金融公司开发分支并将其用于生产代码。)这是真的吗?我无法找到它。
标准特许确实开发了自己的Haskell编译器。我不希望他们向公众提供。我不确定默认是严格的。
该人还提出认为严格评估比懒惰评估更实用的意见
这没有意义,也没有证据支持。事实上,llvm-hs-pure软件包通过选择使用状态monad的严格版本而不是惰性版本来引入bug。而且,像parallel-io包这样的东西是行不通的。
我想在Haskell开发一个程序,我希望避免空间泄漏,并希望有可预测的性能。
在过去的两年里,我没有被懒惰造成的空间泄漏所困扰。我建议改为使用基准测试和分析您的应用程序。编写具有可预测性能的Haskell比添加严格注释并希望您的程序仍然编译更容易。通过理解您的程序,分析和学习功能数据结构,您将获得更好的服务,而不是盲目地添加编译器编译指示以提高程序的性能。
答案 4 :(得分:2)
如果我理解正确,严格的Haskell就不能像我们所知的那样拥有monadic I / O. Haskell中的想法是所有Haskell代码都是纯粹的(包括IO动作,其工作方式类似于State monad),“main”为运行时提供类型IO()的值,然后重复强制在序列运算符上>> ; =。
对于Tekmo的帖子,你可以看一下Robert Harper的博客, * http://existentialtype.wordpress.com/2011/04/24/the-real-point-of-laziness/ 和相关的。它有两种方式。
根据我的经验,懒惰一开始很难,但是你会习惯它并且很好。
懒惰的经典宣传片是休斯的论文“为什么功能性编程很重要”,你应该能够轻松找到它。