2013-02-26 49 views
12

考慮這個功能:Haskell優化器是否在範圍內使用記憶來重複函數調用?

f as = if length as > 100 then length as else 100 

由於函數是純很明顯,長度將在這兩個調用相同。我的問題是Haskell優化器是否將上面的代碼轉換爲以下代碼?

f as = 
    let l = length as 
    in if l > 100 then l else 100 

如果是這樣,那麼哪個級別設置啓用它?如果沒有,那爲什麼?在這種情況下,內存浪費不可能是this answer中解釋的原因,因爲一旦函數執行完成,引入的變量就會被釋放。


請注意,這不是this question重複,因爲當地的範圍,因此可能會得到完全不同的答案。

回答

15

GHC現在確實some CSE by default,因爲-fcse標誌處於打開狀態。

默認情況下打開。啓用通用子表達式排除 優化。如果您有一些您不想共同使用的unsafePerformIO表達式,則關閉此功能會非常有用。

但是,由於引入共享(以及空間泄漏)的問題,它是conservative。 雖然(和this)CSE通過獲得bit better

最後,請注意有一個完整的CSE插件。

如果你有代碼,可以從中受益。

13

即使在這樣的本地設置中,引入共享始終是最優化的情況仍然不明顯。考慮下面這個例子定義

f = if length [1 .. 1000000] > 0 then head [1 .. 1000000] else 0 

與這一個

f = let xs = [1 .. 1000000] in if length xs > 0 then head xs else 0 

,你會發現,在這種情況下,首先表現要好得多,因爲每一個在名單上進行計算的是價格便宜,而第二個版本將導致列表在內存中完全展開length,並且只能在head減少後才能將其丟棄。

+3

儘管存在這個問題,ghc可能會對CSE更積極。你只需要估算你CSEing的價值。一個簡單的估計是基本類型佔用可忽略的空間。 – augustss 2013-02-26 09:14:30

+0

@augustss同意。 – kosmikus 2013-02-26 09:39:45

+0

'length [1 .. 1000000]> 0'是一個便宜的操作?在評估「>」之前是否必須返回「長度」?(在ghci中,當我增加列表大小時,操作會明顯減慢) – 2016-09-12 11:45:17

相關問題