Haskell平臺中的許多函數的實現中有一個非常常見的模式困擾我,但我無法找到解釋。這是關於使用嵌套函數進行優化。Haskell平臺:嵌套函數和優化
原因在where子句中嵌套函數時,他們的目標是使尾遞歸是很清楚,我(在length),但目的是什麼,當內部函數具有完全相同的類型作爲最高一級?它發生,例如,在Data.Set
module的許多功能,如下列之一:
-- | /O(log n)/. Is the element in the set?
member :: Ord a => a -> Set a -> Bool
member = go
where
STRICT_1_OF_2(go)
go _ Tip = False
go x (Bin _ y l r) = case compare x y of
LT -> go x l
GT -> go x r
EQ -> True
#if __GLASGOW_HASKELL__ >= 700
{-# INLINABLE member #-}
#else
{-# INLINE member #-}
#endif
我懷疑它可能有一些做記憶化,但我不知道。
編輯:由於dave4420建議嚴格,這裏是爲STRICT_1_OF_2
宏定義,可以在同一模塊中找到:
-- Use macros to define strictness of functions.
-- STRICT_x_OF_y denotes an y-ary function strict in the x-th parameter.
-- We do not use BangPatterns, because they are not in any standard and we
-- want the compilers to be compiled by as many compilers as possible.
#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined
我瞭解這個宏的作品,但是我仍然不明白爲什麼go
連同STRICT_1_OF_2(go)
不應該被移到頂層而不是member
。
也許這不是因爲優化,而僅僅是因爲文體選擇?
編輯2:我增加了INLINABLE
和INLINE
部從所述一組模塊。我沒有想到,他們乍一看可能會有什麼用處。
我懷疑這與嚴格分析有關:編譯器應該推斷出'member'的第一個參數必須被評估,但'go'的第一個參數總是被評估過。但我不確定。 – dave4420 2012-03-18 10:23:46
@ dave4420:謝謝你的建議。我用一些關於函數嚴格性的更多信息更新了我的問題,我希望這會有所幫助。 – 2012-03-18 10:51:45
我認爲這純粹是一個風格問題。但是你可以通過'go'中的'x'釋放一些微小的增益。我不喜歡這樣寫蜜蜂的風格,因爲它似乎暗示x在每次迭代中都會被seq:ed。另外,當它不一定是(但那很小)時,它在'x'中使成員嚴格。 – augustss 2012-03-18 11:24:16