(Inspirado por mi respuesta a esta pregunta ).
Considere este código (se supone que debe encontrar el elemento más grande que sea menor o igual que una entrada dada):
data TreeMap v = Leaf | Node Integer v (TreeMap v) (TreeMap v) deriving (Show, Read, Eq, Ord)
closestLess :: Integer -> TreeMap v -> Maybe (Integer, v)
closestLess i = precise Nothing where
precise :: Maybe (Integer, v) -> TreeMap v -> Maybe (Integer, v)
precise closestSoFar Leaf = closestSoFar
precise closestSoFar (Node k v l r) = case i `compare` k of
LT -> precise closestSoFar l
EQ -> Just (k, v)
GT -> precise (Just (k, v)) r
Esto no es muy vago. Una vez que GT
se ingresa el caso, sabemos con certeza que el valor de retorno final será Just
algo más que Nothing
, pero Just
aún no estará disponible hasta el final. Me gustaría hacerlo más perezoso para que Just
esté disponible tan pronto como GT
se ingrese el caso. Mi caso de prueba para esto es que quiero Data.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)
evaluar en True
lugar de tocar fondo. Aquí hay una forma en que puedo pensar en hacer esto:
data TreeMap v = Leaf | Node Integer v (TreeMap v) (TreeMap v) deriving (Show, Read, Eq, Ord)
closestLess :: Integer -> TreeMap v -> Maybe (Integer, v)
closestLess _ Leaf = Nothing
closestLess i (Node k v l r) = case i `compare` k of
LT -> closestLess i l
EQ -> Just (k, v)
GT -> Just (precise (k, v) r)
where
precise :: (Integer, v) -> TreeMap v -> (Integer, v)
precise closestSoFar Leaf = closestSoFar
precise closestSoFar (Node k v l r) = case i `compare` k of
LT -> precise closestSoFar l
EQ -> (k, v)
GT -> precise (k, v) r
Sin embargo, ahora me estoy repitiendo: la lógica central ahora está en ambos closestLess
y en precise
. ¿Cómo puedo escribir esto para que sea flojo pero sin repetirme?