jbe*_*man 17 optimization haskell ghc
根据GHC 文档:
......如果完全应用GHC,GHC将仅内联函数,其中"完全应用"意味着应用于在函数定义的LHS上出现(语法上)的参数.
给出的示例是两个语义等效的定义:
comp1 :: (b -> c) -> (a -> b) -> a -> c
{-# INLINE comp1 #-}
comp1 f g = \x -> f (g x)
comp2 :: (b -> c) -> (a -> b) -> a -> c
{-# INLINE comp2 #-}
comp2 f g x = f (g x)
Run Code Online (Sandbox Code Playgroud)
我的问题:
只有在存在INLINE编译指示的情况下才能获得这种严格的行为(即LHS的严格句法视图,RHS内联w/out优化)?
没有给出INLINE编译指示时,也曾经GHC转换功能像comp2来comp1?
如果没有,为什么?编译器通常难以查看函数的语义并决定部分应用和INLINE的数量和位置?
如果GHC只是将所有函数转换为let... in带有lambda并且在LHS上没有绑定的级联表达式会发生什么?
如果在这个例子中,c它本身就是一个函数类型呢?我不清楚你的提案在那种情况下会如何解决.
无论如何,肯定有些情况下你不希望所有函数的参数"被拉到前面".例如,您可能有一些这样的代码:
foo :: [Int] -> Int -> Int -> Int
foo list = let
-- expensive precomputation here
bar x y = ...
in \ x y -> bar x y
Run Code Online (Sandbox Code Playgroud)
您希望 foo部分应用,然后为结果函数的多个应用程序共享昂贵的预计算工作.如果你把它拉向前foo list x y,你就不会分享那个昂贵的预计算.(我在严肃的应用程序中遇到过这种情况.)
这是一个很好的问题.我阅读了格拉斯哥Haskell编译器Inliner论文的秘密,获得了一些线索,但没有找到太多.
这是一个手工波浪的解释.GHC其实有时需要comp1到comp2-它称之为"埃塔扩张".有关详细信息,请参阅此主题:http://www.haskell.org/pipermail/glasgow-haskell-users/2011-October/020979.html
还有(或曾经)这个eta扩展可以巧妙地改变严格性的问题.看到这个文档的提交(它似乎不是当前的,所以要么它们还没有被重建,要么已经修复,不确定哪个):http://permalink.gmane.org/gmane .comp.lang.haskell.cvs.ghc/57721
在任何情况下,上述主题都有SPJ解释为什么我们通常希望尽可能朝这个方向前进.所以刻意走向另一个方向,以改善内联似乎有点傻.正如秘密论文所讨论的那样,内联的内联并不是最好的想法 - 让这个实用主义更加直言不讳,以便功能得到内联是否有意义这样做可能会伤害到更多的帮助,更不用说增加代码膨胀,因为模块必须同时保持不同级别的eta-shifted函数.
无论如何,作为一个非常不是核心GHC开发者的人,这似乎是我最有可能的.