【问题标题】:Understanding the different behavior of thunks when GHCi let bindings are involved了解涉及 GHCi let 绑定时 thunk 的不同行为
【发布时间】:2014-07-15 10:20:13
【问题描述】:

我一直在玩 Simon Marlow 关于并行和并发的书中的一些示例 在 Haskell 中编程,偶然发现了一个我不太了解的有趣行为。这真的是关于我试图了解 GHC 的一些内部工作原理。

假设我在 REPL 中执行以下操作:

λ» let x = 1 + 2 :: Int
λ» let z = (x,x)
λ» :sprint x
x = _
λ» :sprint z
z = (_,_)
λ» seq x ()
()
λ» :sprint z
z = (3,3)

好的,这几乎是我所期望的,只是 z 已经被评估为 WHNF。让我们编写一个类似的程序并将其放入一个文件中:

module Thunk where

import Debug.Trace

x :: Int
x = trace "add" $ 1 + 2

z :: (Int,Int)
z = (x,x)

然后在 GHCi 中摆弄它:

λ» :sprint x
x = _
λ» :sprint z
z = _
λ» seq x ()
add
()
λ» :sprint z
z = _
λ» seq z ()
()
λ» z
(3,3)

所以这有点不同:z 不会提前评估为 WHNF。我的问题是:

为什么在执行let z = (x,x) 时,REPL 中的z 被评估为 WHNF,但在从文件加载定义时却没有。我的怀疑是 它与模式绑定有关,但我不知道在哪里查找以进行澄清(也许我完全错了)。我本来希望它以某种方式表现得像文件中的示例。

任何提示或简要解释为什么会发生这种情况?

【问题讨论】:

  • 因为 (,) 是一个构造函数,所以区别对 Haskell 的语义没有影响(:sprint 提供对内部 thunk 实现细节的访问,所以不计算在内。)所以这是一个优化的问题以及 GHC 在不同位置编译 (x,x) 时所做的权衡。其他人可能知道这些情况的确切原因。
  • @ØrjanJohansen 我觉得你的评论应该是一个答案。
  • @Codygman 如果你这么认为。不过,我真的不太了解它,所以我一直希望“其他人”能出现。

标签: haskell lazy-evaluation ghci thunk weak-head-normal-form


【解决方案1】:

因为(,) 是一个构造函数,所以区别对 Haskell 的语义没有影响(:sprint 提供对内部 thunk 实现细节的访问,所以不计算在内。)所以这是一个关于哪些优化和权衡 GHC 的问题在不同位置编译(x,x) 时会这样做。其他人可能知道这些情况的确切原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-16
    • 2015-11-17
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 2018-08-16
    相关资源
    最近更新 更多