(Inspiré par ma réponse à cette question .)
Considérez ce code (il est censé trouver le plus grand élément inférieur ou égal à une entrée donnée):
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
Ce n'est pas très paresseux. Une fois le GTcas entré, nous savons avec certitude que la valeur de retour finale sera Justquelque chose plutôt que Nothing, mais le Justreste n'est pas disponible avant la fin. Je voudrais rendre ce paresseux afin que le Justsoit disponible dès que le GTcas est entré. Mon cas de test pour cela est que je veux Data.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)évaluer Trueplutôt que d'enfoncer. Voici une façon dont je peux penser à faire ceci:
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
Cependant, je me répète maintenant: la logique de base est maintenant à la fois closestLessdans et dans precise. Comment puis-je écrire ceci pour qu'il soit paresseux mais sans me répéter?