2013-01-16 120 views
4

GHC是否可以像中间值一样有效地转换表达式?具有中间值的融合优化

例如

main = print $ f ["aa", "bb", "cc"] 

f x = 
    let a = map (map toUpper) x 
     b = filter (\z -> 'C' /= head z) a 
     c = foldl1 (++) b 
    in c 

似乎具有非常不同的核心输出(与-ddump-simple)比用

f x = foldl1 (++) $ filter (\z -> 'C' /= head z) $ map (map toUpper) x 

可以与中间值的表达式采取(显著)更长的时间来评价?

+0

注意这是使用build/foldr融合,因为您使用的是默认的GHC列表实现。如果您需要流版本,请使用'stream-fusion'软件包。好处将是foldl1融合。 –

+0

两个版本都为我提供了相同的内核,分别为7.6.1和7.2.2(使用'-O'和'-O2')。你使用了哪个版本和优化标志? –

+0

@DanielFischer:我没有使用任何优化标志;我想知道的是“什么时候这些不等价”,而且看起来答案是“不使用优化标记时”。 – amindfv

回答

7

线性使用中间值let绑定等同于将值放在(.)之间。

GHC将通过这些管道熔断。您可以从-ddump-simpl-stats

结果看到let绑定:

15 RuleFired 
    1 ++ 
    1 Class op /= 
    1 Class op show 
    1 Class op showList 
    1 filter 
    1 fold/build 
    1 foldr/app 
    1 map 
    1 neChar#->case 
    3 unpack 
    3 unpack-list 

使用管道:

15 RuleFired 
    1 ++ 
    1 Class op /= 
    1 Class op show 
    1 Class op showList 
    1 filter 
    1 fold/build 
    1 foldr/app 
    1 map 
    1 neChar#->case 
    3 unpack 
    3 unpack-list 

而同样融合工人:

随着let绑定:

Main.main_go = 
    \ (ds_aAz :: [[GHC.Types.Char]]) -> 
    case ds_aAz of _ { 
     [] -> GHC.Types.[] @ [GHC.Types.Char]; 
     : y_aAE ys_aAF -> 
     case GHC.Base.map 
       @ GHC.Types.Char @ GHC.Types.Char GHC.Unicode.toUpper y_aAE 
     of wild1_azI { 
      [] -> 
      GHC.List.badHead 
      `cast` (UnsafeCo (forall a_azK. a_azK) [[GHC.Types.Char]] 
        :: (forall a_azK. a_azK) ~ [[GHC.Types.Char]]); 
      : x_azM ds1_azN -> 
      case x_azM of _ { GHC.Types.C# c2_aAa -> 
      case c2_aAa of _ { 
       __DEFAULT -> 
       GHC.Types.: @ [GHC.Types.Char] wild1_azI (Main.main_go ys_aAF); 
       'C' -> Main.main_go ys_aAF 
      } 

管道:

Main.main_go = 
    \ (ds_aAA :: [[GHC.Types.Char]]) -> 
    case ds_aAA of _ { 
     [] -> GHC.Types.[] @ [GHC.Types.Char]; 
     : y_aAF ys_aAG -> 
     case GHC.Base.map 
       @ GHC.Types.Char @ GHC.Types.Char GHC.Unicode.toUpper y_aAF 
     of wild1_azB { 
      [] -> 
      GHC.List.badHead 
      `cast` (UnsafeCo (forall a_azD. a_azD) [[GHC.Types.Char]] 
        :: (forall a_azD. a_azD) ~ [[GHC.Types.Char]]); 
      : x_azF ds1_azG -> 
      case x_azF of _ { GHC.Types.C# c2_aA3 -> 
      case c2_aA3 of _ { 
       __DEFAULT -> 
       GHC.Types.: @ [GHC.Types.Char] wild1_azB (Main.main_go ys_aAG); 
       'C' -> Main.main_go ys_aAG 
      } 
      } 

你忘了-02编译?