是否有使用严格评估的Haskell编译器或预处理器?

时间:2022-11-14 17:03:50

I'm looking for a Haskell compiler that uses strict evaluation by default instead of lazy evaluation. I would just use OCaml, but Haskell's syntax is so much better than OCaml's (and Haskell is pure, and has cool features such as type classes).

我正在寻找一个Haskell编译器,它默认使用严格的评估而不是懒惰的评估。我只想使用OCaml,但Haskell的语法比OCaml好得多(而且Haskell是纯粹的,并且具有很酷的功能,比如类型类)。

I'd really rather not constantly put !s and $!s all over my program. A compiler with a switch or a preprocessor to put in the strictness annotations would be really nice. It would also be helpful if there was a way to use lazy evaluation in certain places too, just in case I want something like an infinite list (I probably never will).

我真的宁愿不经常把!和$!s全部放在我的程序中。带有开关或预处理器的编译器可以输入严格的注释,这非常好。如果有一种方法在某些地方使用延迟评估也是有帮助的,以防万一我想要无限列表(我可能永远不会)。

Please do not try to convince me that lazy evaluation is better, I really need the performance. IIRC, Simon Peyton Jones even said that lazy evaluation wasn't really necessary, it was there mostly to prevent them from making the language impure.

请不要试图说服懒惰的评价更好,我真的需要表现。 IIRC,西蒙佩顿琼斯甚至说懒惰的评价并不是真的有必要,主要是为了防止他们使语言不纯洁。

11 个解决方案

#1


If you have a Haskell compiler that uses strict evaluation, it doesn't compile Haskell. Laziness Non-strictness is part of the Haskell spec!

如果你有一个使用严格评估的Haskell编译器,它不会编译Haskell。懒惰非严格性是Haskell规范的一部分!

However, there are alternatives.

但是,还有其他选择。

  • DDC is an attempt to create an explicitly lazy variant of Haskell which supports things like destructive update whilst retaining all the rest of Haskell's goodness. There is one problem: the compiler is currently only in the α-stage, although it seems to be at least usable.

    DDC试图创建一个显式惰性的Haskell变体,它支持破坏性更新之类的东西,同时保留Haskell所有其余的优点。有一个问题:编译器目前只处于α阶段,尽管它似乎至少可用。

  • Create a preprocessor, as others have done.

    像其他人一样创建预处理器。

  • Learn to use Haskell “the right way”. If you can simplify your test case down to something which is publicly-displayable, you could post it on the Haskell-Café mailing list, where people are very helpful with these sorts of questions concerning the effects of non-strictness.

    学会以“正确的方式”使用Haskell。如果您可以将测试用例简化为可公开显示的内容,则可以将其发布在Haskell-Café邮件列表中,在这些列表中,人们对这些关于非严格性影响的问题非常有帮助。

#2


I'd really rather not constantly put !s and $!s all over my program

我真的宁愿不经常把!和$!s全部放在我的程序中

You're doing it wrong, if that's how you're programming Haskell :) You simply won't need to do this. Use GHC, use -O2, use strict data types when appropriate, use lazy ones when appropriate. Don't assume laziness is going to be a problem - it is a solution to a lot of problems.

你做错了,如果你正在编程Haskell :)你根本不需要这样做。使用GHC,使用-O2,在适当的时候使用严格的数据类型,在适当的时候使用懒惰的数据类型。不要认为懒惰会成为一个问题 - 这是解决许多问题的方法。

#3


There have been two attempts at strictly evaluating Haskell in the past:

过去有两次严格评估Haskell的尝试:

  • Jan-Willem Maessen's Eager Haskell
  • Jan-Willem Maessen的渴望Haskell

  • Rob Ennals PhD thesis
  • Rob Ennals博士论文

But both were focused on sticking to Haskell's non-strict semantics but using a mostly-strict evaluation strategy, rather than actually changing the semantics, and neither ever really saw the light of day.

但两者都专注于坚持Haskell的非严格语义,但使用了一种大多数严格的评估策略,而不是实际改变语义,而且从未真正看到过白昼。

Edit: Martijn's suggestion of strict-plugin looks ideal for your purposes as it actually does what you want and the author is still active in the Haskell community, I'd forgotten about it.

编辑:Martijn对strict-plugin的建议看起来非常适合您的目的,因为它实际上做了您想要的并且作者仍然活跃在Haskell社区中,我已经忘记了它。

#4


See also ghc-strict-plugin, an example for GHC's plugin framework, described in the Monad Reader 12.

另请参阅ghc-strict-plugin,这是GHC插件框架的一个示例,在Monad Reader 12中有所描述。

#5


I feel your pain. My biggest PITA in my day-to-day programming is dealing with those !@#$%^&( space leaks.

我感觉到你的痛苦。在我的日常编程中,我最大的PITA就是处理那些!@#$%^&(空间泄漏。

However, if it helps, with time you do learn (the hard way) about how to deal with this, and it does get better. But I'm still waiting for Andy Gill to come out with his magical space leak profiler to fix all of my problems. (I'm taking his off-hand comment to me at the last ICFP that he'd dreamed up this cool idea as a promise to implement it.)

但是,如果它有所帮助,那么随着时间的推移,您将学习(艰难的方法)如何处理这个问题,并且确实会变得更好。但是我还在等待Andy Gill带着他神奇的太空泄漏探测器来解决我的所有问题。 (我在最后一次ICFP上向我发表他的副评论,他认为这个很酷的想法是实现它的承诺。)

I won't try to convince you that lazy evaluation is the best thing in the world, but there are certain good points about it. I've got some stream-processing programs that scoot lazy lists through any variety of combinators that run happily on gigabytes of data while using only 3.5 MB or so of memory (of which more than 2MB is GHC runtime). And someone smarter than I am pointed out to me last year that you would really be quite surprised, as a typical Haskell programmer, how much you depend on lazy evaluation.

我不会试图说服你,懒惰的评价是世界上最好的,但它有一些好处。我有一些流处理程序可以通过任何种类的组合器来搜索惰性列表,这些组合器可以快速运行数十亿字节的数据,同时只使用3.5 MB左右的内存(其中2MB以上是GHC运行时)。还有一个比我去年更聪明的人,你会真的很惊讶,作为一个典型的Haskell程序员,你有多依赖懒惰的评价。

But what we really need is a really good book on dealing with lazy evaluation in the real world (which is not so different from the academic world, really, except they simply don't get a paper published, and we get clients coming after us with knives) that will properly cover most of the issues relating to this and, more importantly, give us an intuitive sense of what's going to explode our heap and what isn't.

但我们真正需要的是一本关于在现实世界中处理懒惰评估的非常好的书(这与学术界没那么不同,实际上,除了他们根本没有发表论文,我们让客户追随我们使用刀具)将适当地涵盖与此相关的大多数问题,更重要的是,让我们直观地了解什么会爆炸我们的堆,什么不是。

I don't think that this is a new thing; I'm sure other languages and architectures have been through this too. How did the first programmers to deal with hardware stacks and all that, after all? Not so well, I bet.

我不认为这是一件新事物;我确信其他语言和架构也经历过这一点。毕竟,第一批程序员是如何处理硬件堆栈的呢?不太好,我敢打赌。

#6


I think that Jan-Willem Maessan's pH compiler is/was strict. The next closest is Robert Ennal's speculative evaluation fork for ghc 5. The spec_eval fork is not strict, but instead optimistically evaluates. I don't know if either of those are still current/usable/etc.

我认为Jan-Willem Maessan的pH编译器是严格的。下一个最接近的是Robert Ennal对ghc 5的推测性评估分析.peclection_eval分支并不严格,而是乐观地评估。我不知道其中任何一个是否仍然是当前/可用/等。

#7


Using nfdata and rnf everywhere isn't a solution since it means repeatedly traversing large structures that have already been evaluated.

在任何地方使用nfdata和rnf都不是解决方案,因为它意味着重复遍历已经评估过的大型结构。

The introductory chapter of Ben Lippmeier's PhD thesis (about DDC) is about the best critique of Haskell that I've seen--it discusses issues of laziness, destructive update, monad transformers, etc. DDC has laziness but you have to request it explicitly, and it's considered an effect, which is tracked and managed by DDC's type-and-effect system.

Ben Lippmeier的博士论文(关于DDC)的介绍性章节是关于我见过的对Haskell的最佳批评 - 它讨论了懒惰,破坏性更新,monad变换器等问题.DDC有懒惰但你必须明确要求它,它被认为是一种效果,由DDC的类型和效果系统跟踪和管理。

#8


I recently saw some work in this area:

我最近在这方面看到了一些工作:

https://ghc.haskell.org/trac/ghc/wiki/StrictPragma

You can hear a tiny bit about it in SPJ's GHC status update here:

您可以在SPJ的GHC状态更新中听到一点关于它的信息:

http://youtu.be/Ex79K4lvJno?t=9m33s (Link starts at the relevant piece at 9:33)

http://youtu.be/Ex79K4lvJno?t=9m33s(链接从9:33的相关部分开始)

#9


I'm looking for a Haskell compiler that uses strict evaluation by default instead of lazy evaluation.

我正在寻找一个Haskell编译器,它默认使用严格的评估而不是懒惰的评估。

Such a compiler would not be a Haskell compiler. If you really want, you could consider putting {-# LANGUAGE Strict #-} pragmas in your files. This will work with GHC 8.0.2, 8.2.2, and 8.4.1, aka the last three releases of the compiler.

这样的编译器不是Haskell编译器。如果你真的想要,你可以考虑在你的文件中添加{ - #LANGUAGE Strict# - } pragma。这将适用于GHC 8.0.2,8.2.2和8.4.1,也就是编译器的最后三个版本。

It would also be helpful if there was a way to use lazy evaluation in certain places too, just in case I want something like an infinite list

如果有某种方法在某些地方使用延迟评估也是有帮助的,以防我想要像无限列表这样的东西

There is no such method. Instead, use GHC as it was intended - as a lazy language. Learning to think about your code, profile, and use functional data structures correctly will be far more useful than mindlessly applying strictness pragmas everywhere. GHC already has a strictness analyzer.

没有这样的方法。相反,按照预期使用GHC - 作为一种懒惰的语言。学会正确地思考你的代码,配置文件和使用功能数据结构比在任何地方盲目地应用严格编译指示要有用得多。 GHC已经有一个严格的分析仪。

(I probably never will).

(我可能永远不会)。

That's exactly what the authors of llvm-hs thought when they chose to use a strict state monad rather than a lazy one. Instead, it caused an unexpected bug down the road. Laziness and recursion go hand-in-hand.

这正是llvm-hs的作者在选择使用严格的状态monad而不是懒惰状态时的想法。相反,它导致了一个意想不到的错误。懒惰和递归是相辅相成的。

Please do not try to convince me that lazy evaluation is better, I really need the performance.

请不要试图说服懒惰的评价更好,我真的需要表现。

I'm dubious this is actually what you want when it doesn't reliably increase performance of Haskell code while simultaneously breaking existing code and making existing resources useless. If this is how you intend to write programs, please just use OCaml or Scala and leave the Haskell community alone.

我怀疑这实际上是你想要的,因为它不能可靠地提高Haskell代码的性能,同时破坏现有代码并使现有资源无用。如果您打算编写程序,请使用OCaml或Scala并单独留下Haskell社区。

IIRC, Simon Peyton Jones even said that lazy evaluation wasn't really necessary, it was there mostly to prevent them from making the language impure.

IIRC,西蒙佩顿琼斯甚至说懒惰的评价并不是真的有必要,主要是为了防止他们使语言不纯洁。

That is not true. You can read more on the actual history of Haskell here

事实并非如此。您可以在这里阅读有关Haskell实际历史的更多信息

#10


There is also seqaid, which aims at the middle of the lazy-strict spectrum.

还有seqaid,它的目标是懒惰严格的光谱中间。

Seqaid is a GHC plugin providing non-invasive auto-instrumentation of Haskell projects, for dynamic strictness (and parallelism) control. This will soon include optimisation for automated space leak relief using minimal strictification.

Seqaid是一个GHC插件,提供Haskell项目的非侵入式自动检测,用于动态严格(和并行)控制。这将很快包括使用最小限度的优化自动化空间泄漏。

#11


You clearly have made up your mind on the value of strict evaluation, but I think you are missing the point of using Haskell. Haskell's lazy evaluation allows for much more flexible optimization strategies to be employed by the compiler/interpreter. Forcing your own strictness overrides the optimizer. In the end, using excessive strict evaluation will never be as efficient as the automated optimization. Try a folding sum over a sequence of numbers in GHCI, with and then without lazy evaluation. You can see the difference quite clearly -- in this case lazy evaluation is always faster.

您显然已经决定了严格评估的价值,但我认为您忽略了使用Haskell的重点。 Haskell的惰性求值允许编译器/解释器采用更灵活的优化策略。强制你自己的严格性会覆盖优化器。最后,使用过度严格的评估将永远不会像自动化优化那样有效。尝试对GHCI中的一系列数字进行折叠求和,然后不进行惰性求值。您可以非常清楚地看到差异 - 在这种情况下,懒惰评估总是更快。

#1


If you have a Haskell compiler that uses strict evaluation, it doesn't compile Haskell. Laziness Non-strictness is part of the Haskell spec!

如果你有一个使用严格评估的Haskell编译器,它不会编译Haskell。懒惰非严格性是Haskell规范的一部分!

However, there are alternatives.

但是,还有其他选择。

  • DDC is an attempt to create an explicitly lazy variant of Haskell which supports things like destructive update whilst retaining all the rest of Haskell's goodness. There is one problem: the compiler is currently only in the α-stage, although it seems to be at least usable.

    DDC试图创建一个显式惰性的Haskell变体,它支持破坏性更新之类的东西,同时保留Haskell所有其余的优点。有一个问题:编译器目前只处于α阶段,尽管它似乎至少可用。

  • Create a preprocessor, as others have done.

    像其他人一样创建预处理器。

  • Learn to use Haskell “the right way”. If you can simplify your test case down to something which is publicly-displayable, you could post it on the Haskell-Café mailing list, where people are very helpful with these sorts of questions concerning the effects of non-strictness.

    学会以“正确的方式”使用Haskell。如果您可以将测试用例简化为可公开显示的内容,则可以将其发布在Haskell-Café邮件列表中,在这些列表中,人们对这些关于非严格性影响的问题非常有帮助。

#2


I'd really rather not constantly put !s and $!s all over my program

我真的宁愿不经常把!和$!s全部放在我的程序中

You're doing it wrong, if that's how you're programming Haskell :) You simply won't need to do this. Use GHC, use -O2, use strict data types when appropriate, use lazy ones when appropriate. Don't assume laziness is going to be a problem - it is a solution to a lot of problems.

你做错了,如果你正在编程Haskell :)你根本不需要这样做。使用GHC,使用-O2,在适当的时候使用严格的数据类型,在适当的时候使用懒惰的数据类型。不要认为懒惰会成为一个问题 - 这是解决许多问题的方法。

#3


There have been two attempts at strictly evaluating Haskell in the past:

过去有两次严格评估Haskell的尝试:

  • Jan-Willem Maessen's Eager Haskell
  • Jan-Willem Maessen的渴望Haskell

  • Rob Ennals PhD thesis
  • Rob Ennals博士论文

But both were focused on sticking to Haskell's non-strict semantics but using a mostly-strict evaluation strategy, rather than actually changing the semantics, and neither ever really saw the light of day.

但两者都专注于坚持Haskell的非严格语义,但使用了一种大多数严格的评估策略,而不是实际改变语义,而且从未真正看到过白昼。

Edit: Martijn's suggestion of strict-plugin looks ideal for your purposes as it actually does what you want and the author is still active in the Haskell community, I'd forgotten about it.

编辑:Martijn对strict-plugin的建议看起来非常适合您的目的,因为它实际上做了您想要的并且作者仍然活跃在Haskell社区中,我已经忘记了它。

#4


See also ghc-strict-plugin, an example for GHC's plugin framework, described in the Monad Reader 12.

另请参阅ghc-strict-plugin,这是GHC插件框架的一个示例,在Monad Reader 12中有所描述。

#5


I feel your pain. My biggest PITA in my day-to-day programming is dealing with those !@#$%^&( space leaks.

我感觉到你的痛苦。在我的日常编程中,我最大的PITA就是处理那些!@#$%^&(空间泄漏。

However, if it helps, with time you do learn (the hard way) about how to deal with this, and it does get better. But I'm still waiting for Andy Gill to come out with his magical space leak profiler to fix all of my problems. (I'm taking his off-hand comment to me at the last ICFP that he'd dreamed up this cool idea as a promise to implement it.)

但是,如果它有所帮助,那么随着时间的推移,您将学习(艰难的方法)如何处理这个问题,并且确实会变得更好。但是我还在等待Andy Gill带着他神奇的太空泄漏探测器来解决我的所有问题。 (我在最后一次ICFP上向我发表他的副评论,他认为这个很酷的想法是实现它的承诺。)

I won't try to convince you that lazy evaluation is the best thing in the world, but there are certain good points about it. I've got some stream-processing programs that scoot lazy lists through any variety of combinators that run happily on gigabytes of data while using only 3.5 MB or so of memory (of which more than 2MB is GHC runtime). And someone smarter than I am pointed out to me last year that you would really be quite surprised, as a typical Haskell programmer, how much you depend on lazy evaluation.

我不会试图说服你,懒惰的评价是世界上最好的,但它有一些好处。我有一些流处理程序可以通过任何种类的组合器来搜索惰性列表,这些组合器可以快速运行数十亿字节的数据,同时只使用3.5 MB左右的内存(其中2MB以上是GHC运行时)。还有一个比我去年更聪明的人,你会真的很惊讶,作为一个典型的Haskell程序员,你有多依赖懒惰的评价。

But what we really need is a really good book on dealing with lazy evaluation in the real world (which is not so different from the academic world, really, except they simply don't get a paper published, and we get clients coming after us with knives) that will properly cover most of the issues relating to this and, more importantly, give us an intuitive sense of what's going to explode our heap and what isn't.

但我们真正需要的是一本关于在现实世界中处理懒惰评估的非常好的书(这与学术界没那么不同,实际上,除了他们根本没有发表论文,我们让客户追随我们使用刀具)将适当地涵盖与此相关的大多数问题,更重要的是,让我们直观地了解什么会爆炸我们的堆,什么不是。

I don't think that this is a new thing; I'm sure other languages and architectures have been through this too. How did the first programmers to deal with hardware stacks and all that, after all? Not so well, I bet.

我不认为这是一件新事物;我确信其他语言和架构也经历过这一点。毕竟,第一批程序员是如何处理硬件堆栈的呢?不太好,我敢打赌。

#6


I think that Jan-Willem Maessan's pH compiler is/was strict. The next closest is Robert Ennal's speculative evaluation fork for ghc 5. The spec_eval fork is not strict, but instead optimistically evaluates. I don't know if either of those are still current/usable/etc.

我认为Jan-Willem Maessan的pH编译器是严格的。下一个最接近的是Robert Ennal对ghc 5的推测性评估分析.peclection_eval分支并不严格,而是乐观地评估。我不知道其中任何一个是否仍然是当前/可用/等。

#7


Using nfdata and rnf everywhere isn't a solution since it means repeatedly traversing large structures that have already been evaluated.

在任何地方使用nfdata和rnf都不是解决方案,因为它意味着重复遍历已经评估过的大型结构。

The introductory chapter of Ben Lippmeier's PhD thesis (about DDC) is about the best critique of Haskell that I've seen--it discusses issues of laziness, destructive update, monad transformers, etc. DDC has laziness but you have to request it explicitly, and it's considered an effect, which is tracked and managed by DDC's type-and-effect system.

Ben Lippmeier的博士论文(关于DDC)的介绍性章节是关于我见过的对Haskell的最佳批评 - 它讨论了懒惰,破坏性更新,monad变换器等问题.DDC有懒惰但你必须明确要求它,它被认为是一种效果,由DDC的类型和效果系统跟踪和管理。

#8


I recently saw some work in this area:

我最近在这方面看到了一些工作:

https://ghc.haskell.org/trac/ghc/wiki/StrictPragma

You can hear a tiny bit about it in SPJ's GHC status update here:

您可以在SPJ的GHC状态更新中听到一点关于它的信息:

http://youtu.be/Ex79K4lvJno?t=9m33s (Link starts at the relevant piece at 9:33)

http://youtu.be/Ex79K4lvJno?t=9m33s(链接从9:33的相关部分开始)

#9


I'm looking for a Haskell compiler that uses strict evaluation by default instead of lazy evaluation.

我正在寻找一个Haskell编译器,它默认使用严格的评估而不是懒惰的评估。

Such a compiler would not be a Haskell compiler. If you really want, you could consider putting {-# LANGUAGE Strict #-} pragmas in your files. This will work with GHC 8.0.2, 8.2.2, and 8.4.1, aka the last three releases of the compiler.

这样的编译器不是Haskell编译器。如果你真的想要,你可以考虑在你的文件中添加{ - #LANGUAGE Strict# - } pragma。这将适用于GHC 8.0.2,8.2.2和8.4.1,也就是编译器的最后三个版本。

It would also be helpful if there was a way to use lazy evaluation in certain places too, just in case I want something like an infinite list

如果有某种方法在某些地方使用延迟评估也是有帮助的,以防我想要像无限列表这样的东西

There is no such method. Instead, use GHC as it was intended - as a lazy language. Learning to think about your code, profile, and use functional data structures correctly will be far more useful than mindlessly applying strictness pragmas everywhere. GHC already has a strictness analyzer.

没有这样的方法。相反,按照预期使用GHC - 作为一种懒惰的语言。学会正确地思考你的代码,配置文件和使用功能数据结构比在任何地方盲目地应用严格编译指示要有用得多。 GHC已经有一个严格的分析仪。

(I probably never will).

(我可能永远不会)。

That's exactly what the authors of llvm-hs thought when they chose to use a strict state monad rather than a lazy one. Instead, it caused an unexpected bug down the road. Laziness and recursion go hand-in-hand.

这正是llvm-hs的作者在选择使用严格的状态monad而不是懒惰状态时的想法。相反,它导致了一个意想不到的错误。懒惰和递归是相辅相成的。

Please do not try to convince me that lazy evaluation is better, I really need the performance.

请不要试图说服懒惰的评价更好,我真的需要表现。

I'm dubious this is actually what you want when it doesn't reliably increase performance of Haskell code while simultaneously breaking existing code and making existing resources useless. If this is how you intend to write programs, please just use OCaml or Scala and leave the Haskell community alone.

我怀疑这实际上是你想要的,因为它不能可靠地提高Haskell代码的性能,同时破坏现有代码并使现有资源无用。如果您打算编写程序,请使用OCaml或Scala并单独留下Haskell社区。

IIRC, Simon Peyton Jones even said that lazy evaluation wasn't really necessary, it was there mostly to prevent them from making the language impure.

IIRC,西蒙佩顿琼斯甚至说懒惰的评价并不是真的有必要,主要是为了防止他们使语言不纯洁。

That is not true. You can read more on the actual history of Haskell here

事实并非如此。您可以在这里阅读有关Haskell实际历史的更多信息

#10


There is also seqaid, which aims at the middle of the lazy-strict spectrum.

还有seqaid,它的目标是懒惰严格的光谱中间。

Seqaid is a GHC plugin providing non-invasive auto-instrumentation of Haskell projects, for dynamic strictness (and parallelism) control. This will soon include optimisation for automated space leak relief using minimal strictification.

Seqaid是一个GHC插件,提供Haskell项目的非侵入式自动检测,用于动态严格(和并行)控制。这将很快包括使用最小限度的优化自动化空间泄漏。

#11


You clearly have made up your mind on the value of strict evaluation, but I think you are missing the point of using Haskell. Haskell's lazy evaluation allows for much more flexible optimization strategies to be employed by the compiler/interpreter. Forcing your own strictness overrides the optimizer. In the end, using excessive strict evaluation will never be as efficient as the automated optimization. Try a folding sum over a sequence of numbers in GHCI, with and then without lazy evaluation. You can see the difference quite clearly -- in this case lazy evaluation is always faster.

您显然已经决定了严格评估的价值,但我认为您忽略了使用Haskell的重点。 Haskell的惰性求值允许编译器/解释器采用更灵活的优化策略。强制你自己的严格性会覆盖优化器。最后,使用过度严格的评估将永远不会像自动化优化那样有效。尝试对GHCI中的一系列数字进行折叠求和,然后不进行惰性求值。您可以非常清楚地看到差异 - 在这种情况下,懒惰评估总是更快。