它显示了ghci在下面所有地方都很懒,
ghci > let x = trace "1" 1 in x + x
1
1
2编译后运行下面的代码显示默认ghc由严格度分析器增强。
main = do print $ let x = trace "1" 1 in x + x
1
2但是,为什么即使将选项-O0 -fno-strictness传递给ghc,结果仍然是相同的?
发布于 2016-12-01 20:49:06
这与严苛无关。如果你想一想,GHCi的行为实际上是愚蠢的:它“计算”x两次。不管懒惰与否,一个常数不需要计算两次!
发生了什么:x有一个泛型数字类型Num a => a。这意味着,它的实现不仅仅是一个常量,而是一个带有“type”(实际上是字典-)参数的函数。函数通常是不可行的回忆录,因此这样的多态值重新计算时,您需要它的价值。这是令人讨厌的,因此标准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幸运的是,在实际程序中,即使关闭了单态限制,也不会发生双重计算,因为当在函数体中定义x时,编译器可以看到在函数范围内它不是多态的。因此,您的第二段代码不应该跟踪1两次。(尽管要记住,trace只是一个粗糙的调试工具,它实际上违背了语言的本质--通常不要指望它有任何可重复的行为。)
https://stackoverflow.com/questions/40919795
复制相似问题