diff options
| author | peb <unknown> | 2005-03-21 13:17:44 +0000 |
|---|---|---|
| committer | peb <unknown> | 2005-03-21 13:17:44 +0000 |
| commit | 96a08c9df49345657c769ac481b6df47cbea3a8d (patch) | |
| tree | 2c9d6dc0603fb1fe70934af8df7b6e1336c83fa4 /src/GF/Data/RedBlackSet.hs | |
| parent | aef9430eb0576964a3fb669c741f1c689724bb5a (diff) | |
"Committed_by_peb"
Diffstat (limited to 'src/GF/Data/RedBlackSet.hs')
| -rw-r--r-- | src/GF/Data/RedBlackSet.hs | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/GF/Data/RedBlackSet.hs b/src/GF/Data/RedBlackSet.hs new file mode 100644 index 000000000..8a1b8a743 --- /dev/null +++ b/src/GF/Data/RedBlackSet.hs @@ -0,0 +1,150 @@ +---------------------------------------------------------------------- +-- | +-- Module : RedBlackSet +-- Maintainer : Peter Ljunglöf +-- Stability : Stable +-- Portability : Haskell 98 +-- +-- > CVS $Date: 2005/03/21 14:17:39 $ +-- > CVS $Author: peb $ +-- > CVS $Revision: 1.1 $ +-- +-- Modified version of Okasaki's red-black trees +-- incorporating sets and set-valued maps +---------------------------------------------------------------------- + +module GF.Data.RedBlackSet ( -- * Red-black sets + RedBlackSet, + rbEmpty, + rbList, + rbElem, + rbLookup, + rbInsert, + rbMap, + rbOrdMap, + -- * Red-black finite maps + RedBlackMap, + rbmEmpty, + rbmList, + rbmElem, + rbmLookup, + rbmInsert, + rbmOrdMap + ) where + +-------------------------------------------------------------------------------- +-- sets + +data Color = R | B deriving (Eq, Show) +data RedBlackSet a = E | T Color (RedBlackSet a) a (RedBlackSet a) + deriving (Eq, Show) + +rbBalance B (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d) +rbBalance B (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d) +rbBalance B a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d) +rbBalance B a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d) +rbBalance color a x b = T color a x b + +rbBlack (T _ a x b) = T B a x b + +-- | the empty set +rbEmpty :: RedBlackSet a +rbEmpty = E + +-- | the elements of a set as a sorted list +rbList :: RedBlackSet a -> [a] +rbList tree = rbl tree [] + where rbl E = id + rbl (T _ left a right) = rbl right . (a:) . rbl left + +-- | checking for containment +rbElem :: Ord a => a -> RedBlackSet a -> Bool +rbElem _ E = False +rbElem a (T _ left a' right) + = case compare a a' of + LT -> rbElem a left + GT -> rbElem a right + EQ -> True + +-- | looking up a key in a set of keys and values +rbLookup :: Ord k => k -> RedBlackSet (k, a) -> Maybe a +rbLookup _ E = Nothing +rbLookup a (T _ left (a',b) right) + = case compare a a' of + LT -> rbLookup a left + GT -> rbLookup a right + EQ -> Just b + +-- | inserting a new element. +-- returns 'Nothing' if the element is already contained +rbInsert :: Ord a => a -> RedBlackSet a -> Maybe (RedBlackSet a) +rbInsert value tree = fmap rbBlack (rbins tree) + where rbins E = Just (T R E value E) + rbins (T color left value' right) + = case compare value value' of + LT -> do left' <- rbins left + return (rbBalance color left' value' right) + GT -> do right' <- rbins right + return (rbBalance color left value' right') + EQ -> Nothing + +-- | mapping each value of a key-value set +rbMap :: (a -> b) -> RedBlackSet (k, a) -> RedBlackSet (k, b) +rbMap f E = E +rbMap f (T color left (key, value) right) + = T color (rbMap f left) (key, f value) (rbMap f right) + +-- | mapping each element to another type. +-- /observe/ that the mapping function needs to preserve +-- the order between objects +rbOrdMap :: (a -> b) -> RedBlackSet a -> RedBlackSet b +rbOrdMap f E = E +rbOrdMap f (T color left value right) + = T color (rbOrdMap f left) (f value) (rbOrdMap f right) + +---------------------------------------------------------------------- +-- finite maps + +type RedBlackMap k a = RedBlackSet (k, RedBlackSet a) + +-- | the empty map +rbmEmpty :: RedBlackMap k a +rbmEmpty = E + +-- | converting a map to a key-value list, sorted on the keys, +-- and for each key, a sorted list of values +rbmList :: RedBlackMap k a -> [(k, [a])] +rbmList tree = [ (k, rbList sub) | (k, sub) <- rbList tree ] + +-- | checking whether a key-value pair is contained in the map +rbmElem :: (Ord k, Ord a) => k -> a -> RedBlackMap k a -> Bool +rbmElem key value = maybe False (rbElem value) . rbLookup key + +-- | looking up a key, returning a (sorted) list of all matching values +rbmLookup :: Ord k => k -> RedBlackMap k a -> [a] +rbmLookup key = maybe [] rbList . rbLookup key + +-- | inserting a key-value pair. +-- returns 'Nothing' if the pair is already contained in the map +rbmInsert :: (Ord k, Ord a) => k -> a -> RedBlackMap k a -> Maybe (RedBlackMap k a) +rbmInsert key value tree = fmap rbBlack (rbins tree) + where rbins E = Just (T R E (key, T B E value E) E) + rbins (T color left item@(key', vtree) right) + = case compare key key' of + LT -> do left' <- rbins left + return (rbBalance color left' item right) + GT -> do right' <- rbins right + return (rbBalance color left item right') + EQ -> do vtree' <- rbInsert value vtree + return (T color left (key', vtree') right) + +-- | mapping each value to another type. +-- /observe/ that the mapping function needs to preserve +-- order between objects +rbmOrdMap :: (a -> b) -> RedBlackMap k a -> RedBlackMap k b +rbmOrdMap f E = E +rbmOrdMap f (T color left (key, tree) right) + = T color (rbmOrdMap f left) (key, rbOrdMap f tree) (rbmOrdMap f right) + + + |
