(この質問に対する私の答えに触発されました。)
次のコードを検討してください(指定された入力以下の最大の要素を見つけることが想定されています)。
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
。これは私がこれを行うと考えることができる1つの方法です:
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
ます。これを怠惰に繰り返すことなく、どのように書くことができますか?