Hay un patrón muy común en la implementación de muchas funciones en la plataforma haskell que me molesta, pero no pude encontrar una explicación. Se trata del uso de funciones anidadas para la optimización.plataforma Haskell: funciones anidadas y optimización
La razón de funciones anidadas en las cláusulas WHERE cuando su objetivo es hacer que la recursión de cola es muy claro para mí (como en length), pero lo que es el objetivo cuando la función interior tiene exactamente el mismo tipo que el de alto nivel uno ? Sucede, en el ejemplo, en muchas funciones del Data.Set
module, como la siguiente:
-- | /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
sospecho que puede tener algo que ver con memoization, pero no estoy seguro.
edición: Desde dave4420 sugiere rigor, aquí es la definición para el STRICT_1_OF_2
macro que se pueden encontrar en el mismo módulo:
-- 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
entiendo cómo funciona esta macro funciona, sin embargo todavía no veo por qué go
junto con STRICT_1_OF_2(go)
no deben moverse al nivel superior en lugar de member
.
Tal vez no sea por una optimización, sino simplemente por una elección estilística.
edición 2: He añadido la parte INLINABLE
y INLINE
desde el módulo de conjunto. No pensé que podrían tener algo que ver con eso a primera vista.
Sospecho que tiene algo que ver con el análisis de rigor: se espera que el compilador infiera que el primer argumento para 'miembro' debe evaluarse pero que el primer argumento para' ir' siempre habrá sido evaluado. Pero no estoy seguro. – dave4420
@ dave4420: Gracias por su sugerencia. Actualicé mi pregunta con más información sobre la rigurosidad de la función, espero que esto ayude. –
Creo que es un problema puramente estilístico. Pero es posible que puedas obtener algo de ganancia al dejar que 'x' sea libre en' go'. No me gusta el estilo en que esto se ha escrito, ya que parece implicar que x se obtiene en cada iteración. Además, hace miembro estricto en 'x' cuando no tiene que ser (pero eso es menor). – augustss