Существует очень распространенная схема реализации многих функций на платформе haskell, которая меня беспокоит, но мне не удалось найти объяснения. Речь идет об использовании вложенных функций для оптимизации.Платформа Haskell: вложенные функции и оптимизация
Причина, по которой вложенные функции в случаях, когда они направлены на создание хвостовой рекурсии, очень ясна для меня (как в 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
@ dave4420: Спасибо за ваше предложение. Я обновил свой вопрос с дополнительной информацией о строгости функции, надеюсь, это поможет. –
Я думаю, что это чисто стилистическая проблема. Но вы, возможно, сможете немного выиграть, позволив 'x' быть свободным в' go'. Мне не нравится стиль, в котором это написано bee, так как это означает, что x получает seq: ed на каждой итерации. Кроме того, он делает член строгим в 'x', когда он не должен быть (но это незначительно). – augustss