gpt4 book ai didi

haskell - 为什么预定义的 `const` 函数在某些上下文中的行为与等效的 lambda 函数不同?

转载 作者:行者123 更新时间:2023-12-01 01:40:00 25 4
gpt4 key购买 nike

在做一些共享实验时,我发现预定义的 const 函数在某些情况下表现不同。

f :: (() -> Int) -> Int
f g = g () + g ()

x1 = f (const (trace "x1" 42))
x2 = f (\_ -> (trace "x2" 42))
x3 = f (myconst (trace "x3" 42))

myconst :: a -> b -> a
myconst x _ = x

this example在没有优化的情况下编译,评估 x1 仅触发一次对 trace 的评估,而对 x2x3 。由于 lambda 函数,这对于 x2 是合理的。

x1
x2
x2
x3
x3
252

definition然而,const 表明它是一个普通的函数定义,没有任何可以解释差异的编译器注释。因此,函数 myconst 的行为应该相同,但事实并非如此。如何解释这种行为,是否有办法在这方面影响编译器?

最佳答案

如果myconst被编译成一个单独的模块(即使这个单独的模块是用-O0编译的),那么输出是:

x1
x2
x2
x3
252

不同之处在于 -- 在 -O0 代码中 -- 在单独的模块中调用 myconst 生成代码:

let x' = myconst (trace "x3" 42) in x' + x'

但是在同一个模块中调用 myconst 会像这样内联它:

trace "x4" 42 + trace "x4" 42

使用 -O2 编译完全改变了代码——所有内容都是内联的,跟踪被提升到表达式的顶部,因此它们每个只执行一次。

您可以在这方面明显地影响编译器,例如将 myconst 放在一个单独的模块中,或者——正如@leftroundabout 所指出的——通过添加各种内联编译指示。

我认为您不能可靠地在这方面影响编译器,而且我不确定您可以通过研究未优化的编译输出了解多少真实世界的 GHC 代码。我认为上面的示例清楚地表明,使用 -O0 生成的代码将根据编译的次要方面以完全任意和矛盾的方式运行,而这些方面您并不认为重要。

关于haskell - 为什么预定义的 `const` 函数在某些上下文中的行为与等效的 lambda 函数不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59294749/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com