我们都知道(或者应该知道)Haskell 默认是懒惰的。在必须评估之前,不会评估任何事物。那么什么时候必须评估某些东西呢? Haskell 有些地方必须严格。我将这些称为“严格点”,尽管这个特定术语并不像我想象的那么广泛。据我说:
Reduction (or evaluation) in Haskell only occurs at strictness points.
所以问题是:Haskell 的严格点准确地说是什么?我的直觉是 main
、seq
/bang 模式、模式匹配以及通过 main
执行的任何 IO
操作是主要的严格点,但我真的不知道为什么我知道这一点。
(另外,如果它们不称为“严格点”,那么它们叫什么?)
我想一个好的答案将包括一些关于 WHNF 等的讨论。我还想象它可能会涉及 lambda 演算。
<小时/>编辑:关于此问题的其他想法。
正如我对这个问题的反射(reflection),我认为在严格点的定义中添加一些内容会更清楚。严格性点可以具有不同的上下文和不同的深度(或严格性)。回到我的定义“Haskell 中的约简仅发生在严格点”,让我们在该定义中添加以下子句:“严格点仅在其周围上下文被求值或约简时才会触发。”
所以,让我尝试让您开始了解我想要的答案。 main
是一个严格点。它被特别指定为其上下文的主要严格点:程序。当程序(main
的上下文)被评估时,main 的严格点被激活。 Main 的深度是最大的:必须对其进行全面评估。 Main通常由IO Action 组成,这也是严格点,其上下文是main
。
现在你尝试:用这些术语讨论 seq 和模式匹配。解释一下函数应用的细微差别:它有多严格?怎么不呢? deepseq
怎么样? let
和 case
语句? unsafePerformIO
? 调试.Trace
?顶级定义?严格的数据类型?刘海图案?等等。其中有多少项可以仅用 seq 或模式匹配来描述?
最佳答案
一个好的起点是理解这篇论文:A Natural Semantics for Lazy Evalution (朗奇伯里)。这将告诉您何时对类似于 GHC Core 的小语言评估表达式。那么剩下的问题是如何将完整的 Haskell 映射到 Core,而大部分翻译是由 Haskell 报告本身给出的。在 GHC 中,我们将此过程称为“脱糖”,因为它去除了语法糖。
嗯,这不是故事的全部,因为 GHC 在脱糖和代码生成之间进行了大量的优化,并且其中许多转换将重新排列核心,以便在不同的时间评估事物(特别是严格性分析会导致事物提前评估)。所以要真正了解你的 程序将被评估,您需要查看GHC生成的Core。
也许这个答案对你来说有点抽象(我没有具体提到 bang 模式或 seq),但你要求一些精确的东西,这就是我们能做的最好的事情。
关于haskell - Haskell 的严格点是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7490768/