(Lấy cảm hứng từ câu trả lời của tôi cho câu hỏi này .)
Xem xét mã này (phải tìm phần tử lớn nhất nhỏ hơn hoặc bằng một đầu vào đã cho):
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
Điều này không phải là rất lười biếng. Khi GT
vụ kiện được nhập vào, chúng tôi biết chắc chắn rằng giá trị trả lại cuối cùng sẽ là Just
một cái gì đó chứ không phải là Nothing
, nhưng Just
vẫn không có sẵn cho đến khi kết thúc. Tôi muốn làm cho cái này lười hơn để nó Just
có sẵn ngay khi GT
vụ án được đưa vào. Trường hợp thử nghiệm của tôi cho điều này là tôi muốn Data.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)
đánh giá True
thay vì chạm đáy. Đây là một cách tôi có thể nghĩ để làm điều này:
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
Tuy nhiên, bây giờ tôi đang lặp lại chính mình: logic cốt lõi bây giờ là cả hai closestLess
và trong precise
. Làm thế nào tôi có thể viết điều này để nó lười biếng nhưng không lặp lại chính mình?