--
-- An efficient implementation of maps from keys to values (dictionaries).
--
--- This module is intended to be imported @qualified@, to avoid name
--- clashes with Prelude functions. eg.
+-- Since many function names (but not the type name) clash with
+-- "Prelude" names, this module is usually imported @qualified@, e.g.
--
--- > import Data.Map as Map
+-- > import Data.Map (Map)
+-- > import qualified Data.Map as Map
--
-- The implementation of 'Map' is based on /size balanced/ binary trees (or
-- trees of /bounded balance/) as described by:
-- ** Insertion
, insert
, insertWith, insertWithKey, insertLookupWithKey
+ , insertWith', insertWithKey'
-- ** Delete\/Update
, delete
, updateMaxWithKey
, minView
, maxView
+ , minViewWithKey
+ , maxViewWithKey
-- * Debugging
, showTree
Bin sz k x l r -> sz
--- | /O(log n)/. Lookup the value at a key in the map.
+-- | /O(log n)/. Lookup the value at a key in the map.
+--
+-- The function will
+-- @return@ the result in the monad or @fail@ in it the key isn't in the
+-- map. Often, the monad to use is 'Maybe', so you get either
+-- @('Just' result)@ or @'Nothing'@.
lookup :: (Monad m,Ord k) => k -> Map k a -> m a
lookup k t = case lookup' k t of
Just x -> return x
insertWith f k x m
= insertWithKey (\k x y -> f x y) k x m
+-- | Same as 'insertWith', but the combining function is applied strictly.
+insertWith' :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
+insertWith' f k x m
+ = insertWithKey' (\k x y -> f x y) k x m
+
+
-- | /O(log n)/. Insert with a combining function.
-- @'insertWithKey' f key value mp@
-- will insert the pair (key, value) into @mp@ if key does
GT -> balance ky y l (insertWithKey f kx x r)
EQ -> Bin sy kx (f kx x y) l r
+-- | Same as 'insertWithKey', but the combining function is applied strictly.
+insertWithKey' :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a
+insertWithKey' f kx x t
+ = case t of
+ Tip -> singleton kx x
+ Bin sy ky y l r
+ -> case compare kx ky of
+ LT -> balance ky y (insertWithKey' f kx x l) r
+ GT -> balance ky y l (insertWithKey' f kx x r)
+ EQ -> let x' = f kx x y in seq x' (Bin sy kx x' l r)
+
+
-- | /O(log n)/. The expression (@'insertLookupWithKey' f k x map@)
-- is a pair where the first element is equal to (@'lookup' k map@)
-- and the second element equal to (@'insertWithKey' f k x map@).
Bin sx kx x l r -> balance kx x l (updateMaxWithKey f r)
Tip -> Tip
--- | /O(log n)/. Retrieves the minimal key of the map, and the map stripped from that element
+-- | /O(log n)/. Retrieves the minimal (key,value) pair of the map, and the map stripped from that element
+-- @fail@s (in the monad) when passed an empty map.
+minViewWithKey :: Monad m => Map k a -> m ((k,a), Map k a)
+minViewWithKey Tip = fail "Map.minView: empty map"
+minViewWithKey x = return (deleteFindMin x)
+
+-- | /O(log n)/. Retrieves the maximal (key,value) pair of the map, and the map stripped from that element
+-- @fail@s (in the monad) when passed an empty map.
+maxViewWithKey :: Monad m => Map k a -> m ((k,a), Map k a)
+maxViewWithKey Tip = fail "Map.maxView: empty map"
+maxViewWithKey x = return (deleteFindMax x)
+
+-- | /O(log n)/. Retrieves the minimal key\'s value of the map, and the map stripped from that element
-- @fail@s (in the monad) when passed an empty map.
-minView :: Monad m => Map k a -> m (Map k a, (k,a))
+minView :: Monad m => Map k a -> m (a, Map k a)
minView Tip = fail "Map.minView: empty map"
-minView x = return (swap $ deleteFindMin x)
+minView x = return (first snd $ deleteFindMin x)
--- | /O(log n)/. Retrieves the maximal key of the map, and the map stripped from that element
+-- | /O(log n)/. Retrieves the maximal key\'s value of the map, and the map stripped from that element
-- @fail@s (in the monad) when passed an empty map.
-maxView :: Monad m => Map k a -> m (Map k a, (k,a))
+maxView :: Monad m => Map k a -> m (a, Map k a)
maxView Tip = fail "Map.maxView: empty map"
-maxView x = return (swap $ deleteFindMax x)
+maxView x = return (first snd $ deleteFindMax x)
-swap (a,b) = (b,a)
+-- Update the 1st component of a tuple (special case of Control.Arrow.first)
+first :: (a -> b) -> (a,c) -> (b,c)
+first f (x,y) = (f x, y)
{--------------------------------------------------------------------
Union.