OrdSet.hs

-- Copyright (c) 1982-1999 Lennart Augustsson, Thomas Johnsson
-- See LICENSE for the full license.
--
module OrdSet (
	OrdSet,
	empty, singleton, union, unionMany, add, addMany,
	-- intersect, delete, deleteMany, minus, 
	-- map, partition, filter, foldl, foldr,
	toList, fromList,
	length, 
	null, isSingleton, 
	-- intersecting, isSubsetOf, 
	elem
	-- replaceMaybe, substitute
	) where
import Prelude hiding (null,length,elem)

-- @@ Sets of ordered items.

-- Red-Black trees.
-- Implementation based on work by Norris Boyd, Andrew W. Appel,
-- David R. Tarditi, and Stephen J. Bevan.

data Colour = Red | Black deriving (Eq)

data OrdSet a
    = Empty
    | Node a Colour (OrdSet a) (OrdSet a)

instance (Eq a) => Eq (OrdSet a) where -- different trees may represent equal sets (XX ?)
    s1 == s2 = toList s1 == toList s2

instance (Ord a, Show a) => Show (OrdSet a) where
	showsPrec p x = showString "OrdSet:" . showsPrec p (toList x)
{-
	showsType x = showString "(OrdSet " . showsType (f x) . showString ")"
		where f :: (Ord a) => OrdSet a -> a
		      f _ = error "OrdSet.f"
-}
rbiR :: a -> OrdSet a -> OrdSet a -> OrdSet a
rbiR k (Node sk Red sl@(Node _ ed _ _) sr) (Node lk Red ll lr) =
    Node k Red (Node lk Black ll lr) (Node sk Black sl sr)

rbiR k (Node sk Red sl sr@(Node _ Red _ _)) (Node lk Red ll lr) =
    Node k Red (Node lk Black ll lr) (Node sk Black sl sr)

rbiR k (Node sk Red sl@(Node slk Red sll slr) sr) l =
    Node slk Black (Node k Red l sll) (Node sk Red slr sr)

rbiR k (Node sk Red sl sr@(Node _ Red _ _)) l =
    Node sk Black (Node k Red l sl) sr

rbiR k t l = Node k Black l t

rbiL :: a -> OrdSet a -> OrdSet a -> OrdSet a
rbiL k (Node lk Red ll lr@(Node _ Red _ _)) (Node rk Red rl rr) =
    Node k Red (Node lk Black ll lr) (Node rk Black rl rr)

rbiL k (Node lk Red ll@(Node _ Red _ _) lr) (Node rk Red rl rr) =
    Node k Red (Node lk Black ll lr) (Node rk Black rl rr)

rbiL k (Node lk Red ll lr@(Node lrk Red lrl lrr)) r =
    Node lrk Black (Node lk Red ll lrl) (Node k Red lrr r)

rbiL k (Node lk Red ll@(Node llk Red lll llr) lr) r =
    Node lk Black ll (Node k Red lr r)

rbiL k t r = Node k Black t r

rbi :: (Ord a) => a -> OrdSet a -> OrdSet a
rbi e Empty = Node e Red Empty Empty
rbi e t@(Node k Black l r) =
	if e <= k then
	    if e == k then
		Node e Black l r
	    else
		rbiL k (rbi e l) r
	else
	    rbiR k (rbi e r) l
rbi e t@(Node k Red l r) =
	if e <= k then
	    if e == k then
		Node e Red l r
	    else
		Node k Red (rbi e l) r
	else
	    Node k Red l (rbi e r)

-- Empty table.
empty :: OrdSet a
empty = Empty

singleton :: a -> OrdSet a
singleton k = Node k Black Empty Empty

-- XXX awful!
union :: (Ord a) => OrdSet a -> OrdSet a -> OrdSet a
union t1 t2 =
	f t2 (toList' t1 [])
	where f t [] = t
	      f t (x:xs) =
		case add x t of	-- just to force evaluation to avoid space leak
		Empty -> error "union"
		t' -> f t' xs

unionMany :: (Ord a) => [OrdSet a] -> OrdSet a
unionMany ts = foldr union empty ts

add :: (Ord a) => a -> OrdSet a -> OrdSet a
add e t =
    case rbi e t of
        Node k Red l@(Node _ Red _ _) r -> Node k Black l r
        Node k Red l r@(Node _ Red _ _) -> Node k Black l r
        x                               -> x

addMany :: (Ord a) => [a] -> OrdSet a -> OrdSet a
addMany is s = foldr add s is

-- Look up an element.
elem :: (Ord a) => a -> OrdSet a -> Bool
elem _ Empty = False
elem e (Node k _ l r) =
	if e <= k then
	    e == k || elem e l
	else elem e r

fromList :: (Ord a) => [a] -> OrdSet a
fromList l = foldr add Empty l

toList t = toList' t []
toList' Empty xs = xs
toList' (Node k _ l r) xs = toList' l (k : toList' r xs)

null Empty = True
null _ = False

isSingleton :: OrdSet a -> Bool
isSingleton (Node _ _ Empty Empty) = True
isSingleton _ = False

length :: OrdSet a -> Int
length Empty = 0
length (Node _ _ l r) = 1 + length l + length r

Plain-text version of OrdSet.hs | Valid HTML?