haskellプラットフォームの多くの関数の実装には非常に一般的なパターンがあり、私を悩ませていますが、説明を見つけることができませんでした。最適化のための入れ子関数の使用についてです。
末尾再帰を目的とするwhere句の入れ子関数の理由は(長さのように)私には非常に明確ですが、内部関数が最上位の関数とまったく同じタイプである場合の目的は何ですか?これは、たとえば、次のような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
このマクロがどのように機能するかは理解していますが、なぜ一緒にをSTRICT_1_OF_2(go)
の代わりにトップレベルに移動すべきでないのかはまだわかりませんmember
。
多分それは最適化のためではなく、単に文体の選択のためですか?
編集2 :セットモジュールからINLINABLE
とパーツを追加しました。INLINE
一見、彼らが何か関係があるとは思いませんでした。