(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 GTvụ 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à Justmột cái gì đó chứ không phải là Nothing, nhưng Justvẫ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ó Justcó sẵn ngay khi GTvụ á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á Truethay 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 closestLessvà 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?