1 Mar 2010 03:27
Proposed additions to Data.Map: lookupFloor and lookupCeiling
Leon Smith <leon.p.smith <at> gmail.com>
2010-03-01 02:27:56 GMT
2010-03-01 02:27:56 GMT
Hi, here are two quick, modest additions to Data.Map. As Map is
exported abstractly, lookupFlor can't be defined outside the library
except via splitLookup and findMax. On the other hand, these
implementations should be nearly the same cost as a regular lookup.
Best,
Leon
-- | /O(log n)/. Find the greatest key that is smaller or equal
-- to the given target key. This \"floor\" key is returned, along with it's
-- associated value, as <at> 'Just' (key, value) <at> . If the map does not have
-- a key that is smaller or equal to the target key, then this function
-- returns 'Nothing'.
lookupFloor :: Ord k => k -> Map k a -> Maybe (k,a)
lookupFloor = go Tip
where
go s k t
= case t of
Tip -> case s of
Tip -> Nothing
Bin _ ka a _ _ -> Just (ka,a)
Bin _ ka a l r
-> case compare ka k of
LT -> go t k r
GT -> go s k l
EQ -> Just (ka,a)
-- | /O(log n)/. Find the smallest key that is greater or equal
-- to the given target key. This \"ceiling\" key is returned, along with it's
(Continue reading)
For example:
ghci> let map = Map.fromList [ (x, ()) | x <- [0,10..1000] ]
ghci> lookupFloor 75 map
Just (70, ())
ghci> floor 7.5
7
ghci> lookupCeiling 115 map
Just (120,())
ghci> ceiling 11.5
12
But honestly I almost invariably get the definitions of floor and
ceiling wrong unless I stop to think for a few seconds. I've trained
myself to do that.
Maybe a few examples in the haddocks would
be in order. That's easier to comprehend, if you know approximately
what it should do.
Also, it occurs to me that maybe a combined function :: (Ord k) => k
-> Map k v -> (Maybe k v, Maybe k v) would be useful in addition to
or in place of lookupFloor and lookupCeiling. But I'm not sure.
Best,
Leon
RSS Feed