There's a very common pattern in the implementation of many functions in the haskell platform that bothers me, but I wasn't able to find an explanation. It's about the use of nested functions for optimization.
The reason for nested functions in where clauses when they aim to make tail recursion is very clear to me (as in length), but what is the purpose when the inner function has exactly the same type as the top-level one? It happens, in example, in many functions of the Data.Set
module, like the following one:
-- | /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
I suspect it may have something to do with memoization, but I'm not sure.
edit: Since dave4420 suggests strictness, here is the definition for the STRICT_1_OF_2
macro that can be found in the same module:
-- 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
I understand how this macro works, however I still do not see why go
together with STRICT_1_OF_2(go)
shouldn't be moved at top-level in place of member
.
Maybe it's not because of an optimization, but simply because of a stylistic choice?
edit 2: I added the INLINABLE
and INLINE
part from the set module. I did not thought that they could have something to do with it at first glance.
member
must be evaluated but that the first argument togo
will always already have been evaluated. But I'm not sure. – Sensualistx
be free ingo
. I don't like the style in which this has bee written, since it seems to imply that x gets seq:ed in every iteration. Also, it makes member strict inx
when it doesn't have to be (but that's minor). – Braga