在haskell平台中实现许多功能时有一个非常常见的模式让我很困扰,但我找不到解释。这是关于使用嵌套函数进行优化。
where 子句中的嵌套函数旨在进行尾递归的原因对我来说非常清楚(如length),但是当内部函数与顶层函数具有完全相同的类型时,目的是什么?例如,它发生在Data.Set
模块的许多功能中,如下所示:
-- | /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
with来代替.STRICT_1_OF_2(go)
member
也许不是因为优化,而仅仅是因为风格选择?
编辑 2:我添加了 set 模块中的INLINABLE
andINLINE
部分。乍一看,我没想到他们可能与此有关。