rai*_*hoo 42 haskell lazy-evaluation ghci thunk weak-head-normal-form
我一直在玩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)
Run Code Online (Sandbox Code Playgroud)
好吧,这几乎是我的预期,除了z已经被评估为WHNF.让我们编写一个类似的程序并将其放在一个文件中:
module Thunk where
import Debug.Trace
x :: Int
x = trace "add" $ 1 + 2
z :: (Int,Int)
z = (x,x)
Run Code Online (Sandbox Code Playgroud)
在GHCi中摆弄它:
?» :sprint x
x = _
?» :sprint z
z = _
?» seq x ()
add
()
?» :sprint z
z = _
?» seq z ()
()
?» z
(3,3)
Run Code Online (Sandbox Code Playgroud)
所以这个行为有点不同:z
不提前评估给WHNF.我的问题是:
为什么z
在执行时在REPL中评估为WHNF,let z = (x,x)
而不是在从文件加载定义时.我怀疑它与模式绑定有关,但我不知道在哪里查看澄清(也许我只是完全错了).我原以为它会以某种方式表现得像文件中的例子.
任何指针或简要解释为什么会发生这种情况?
因为(,)
是一个构造函数,所以这种差异对 Haskell 的语义没有影响(:sprint
可以访问内部 thunk 实现细节,所以不算数。)所以这是一个 GHC 在(x,x)
不同位置编译时进行哪些优化和权衡的问题。其他人可能知道这些情况的确切原因。
归档时间: |
|
查看次数: |
505 次 |
最近记录: |