我一直在玩 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。我的问题是:
为什么z
在执行时会在 REPL 中评估为 WHNF,let z = (x,x)
但在从文件加载定义时不会。我怀疑它与模式绑定有关,但我不知道在哪里查找以进行澄清(也许我完全错了)。我本来希望它以某种方式表现得像文件中的示例。
任何指示或简要解释为什么会发生这种情况?