(ได้แรงบันดาลใจจากคำตอบของคำถามนี้ )
พิจารณารหัสนี้ (มันควรจะหาองค์ประกอบที่ใหญ่ที่สุดที่น้อยกว่าหรือเท่ากับอินพุตที่กำหนด):
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
มันไม่ขี้เกียจมาก เมื่อGT
ป้อนเคสแล้วเรารู้ว่าค่าตอบแทนคืนสุดท้ายจะเป็นJust
อะไรที่มากกว่าNothing
แต่Just
ก็ยังไม่สามารถใช้ได้จนกว่าจะหมด ฉันต้องการทำให้คนนี้Just
ใช้งานได้เร็วขึ้นเมื่อGT
มีการป้อนเคส กรณีทดสอบของฉันสำหรับเรื่องนี้คือฉันต้องการData.Maybe.isJust $ closestLess 5 (Node 3 () Leaf undefined)
ประเมินให้True
มากกว่าการทำจุดต่ำสุด นี่เป็นวิธีหนึ่งที่ฉันสามารถทำได้:
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
แต่ตอนนี้ผมกำลังทำซ้ำตัวเอง: ตรรกะหลักอยู่ในขณะนี้ทั้งในและclosestLess
precise
ฉันจะเขียนสิ่งนี้เพื่อให้มันขี้เกียจ แต่ไม่ทำซ้ำตัวเองได้อย่างไร