(受到我对这个问题的回答的启发。)
考虑下面的代码(它应该找到小于或等于给定输入的最大元素):
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
。我该怎么写,以免偷懒,却又不重复自己?