(Inspiriert von meiner Antwort auf diese Frage .)
Betrachten Sie diesen Code (er soll das größte Element finden, das kleiner oder gleich einer bestimmten Eingabe ist):
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
Das ist nicht sehr faul. Sobald der GTFall eingegeben ist, wissen wir sicher, dass der endgültige Rückgabewert Justeher etwas als sein wird Nothing, aber der Wert Justist erst am Ende verfügbar. Ich möchte dies fauler machen, damit das Justverfügbar ist, sobald der GTFall eingegeben wird. Mein Testfall dafür ist, dass ich eher Data.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)bewerten Trueals auf den Grund gehen möchte . Hier ist eine Möglichkeit, wie ich mir das vorstellen kann:
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
Jetzt wiederhole ich mich jedoch: Die Kernlogik ist jetzt in beiden closestLessund in precise. Wie kann ich das so schreiben, dass es faul ist, ohne mich zu wiederholen?