Платформа Haskell: вложенные функции и оптимизация

В реализации многих функций на платформе 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

Подозреваю, что это как-то связано с мемоизацией, но не уверен .


edit: Поскольку 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.

Может, это не из-за оптимизации, а просто из-за стилистического выбора?


edit 2: я добавил часть INLINABLEи INLINEиз установленного модуля. Не думал, что они могут иметь к этому какое-то отношение на первый взгляд.

20
задан Riccardo T. 18 March 2012 в 11:05
поделиться