(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 GT
Fall eingegeben ist, wissen wir sicher, dass der endgültige Rückgabewert Just
eher etwas als sein wird Nothing
, aber der Wert Just
ist erst am Ende verfügbar. Ich möchte dies fauler machen, damit das Just
verfügbar ist, sobald der GT
Fall eingegeben wird. Mein Testfall dafür ist, dass ich eher Data.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)
bewerten True
als 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 closestLess
und in precise
. Wie kann ich das so schreiben, dass es faul ist, ohne mich zu wiederholen?