(Inspirado pela minha resposta a esta pergunta .)
Considere este código (ele deve encontrar o maior elemento que é menor ou igual a uma determinada entrada):
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
Isso não é muito preguiçoso. Depois que o GTcaso é inserido, sabemos com certeza que o valor final de retorno será Justalgo em vez de Nothing, mas o Justainda não estará disponível até o final. Eu gostaria de tornar isso mais preguiçoso para que ele Justfique disponível assim que o GTcaso for inserido. Meu caso de teste para isso é que eu quero Data.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)avaliar em Truevez de chegar ao fundo. Aqui está uma maneira de pensar em fazer isso:
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
No entanto, agora estou me repetindo: a lógica principal está agora em ambos closestLesse em precise. Como posso escrever isso para que seja preguiçoso, mas sem me repetir?