sof*_*sof 0 haskell lazy-evaluation
它表明ghci下面是懒惰的,
ghci > let x = trace "1" 1 in x + x
1
1
2
Run Code Online (Sandbox Code Playgroud)
编译后运行下面的代码显示默认值ghc由严格性分析器增强.
main = do print $ let x = trace "1" 1 in x + x
1
2
Run Code Online (Sandbox Code Playgroud)
但是,即使将选项-O0 -fno-strictness传递给结果,为什么结果仍然相同ghc?
这与严格无关.如果你想一想,GHCi的行为实际上是愚蠢的:它"计算" x两次.懒惰与否,常数不应该被计算两次!
发生了什么:x有一个通用数字类型Num a => a.这意味着,它的实现并不仅仅是一个常量,而是一个带有"类型"的函数 - (实际上是一个字典 - )参数.功能一般不memoise可行的,所以这样的多态值是当你需要它的价值重新计算.这很烦人,因此标准的Haskell通过一种有争议的措施避免了这一点,即单态性限制.它基本上消除了多态性,如果它可以因此将值转换为恒定的应用形式.因此x推断出更简单的类型Integer,然后是一个常量,它只触发trace一次计算,而第二次评估只是重新使用已知的值.(这是"适当的懒惰"行为!)
你在GHCi中没有看到这个的原因是,自版本7.8以来,它默认关闭了单态限制!您可以将其打开以查看其功能:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :m +Debug.Trace
Prelude Debug.Trace> let x = trace "1" 1 in x + x
1
1
2
Prelude Debug.Trace> :set -XMonomorphismRestriction
Prelude Debug.Trace> let x = trace "1" 1 in x + x
1
2
Run Code Online (Sandbox Code Playgroud)
幸运的是,在实际程序中,即使关闭单态性限制也不会发生双重评估,因为x在函数体中定义时,编译器可以看到在函数范围内,它不是多态的.因此,您的第二个代码永远不会跟踪1两次 (尽管总是记住,trace它只是一个粗略的调试工具,它真正对付语言的粒度 - 通常不会指望它有任何可重现的行为.)
| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |