TernaryTrees-0.1.3.0: Data/Set/TernarySet.hs
module Data.Set.TernarySet (
TernarySet,
insert,
singleton,
member,
size,
fromList,
null,
elems,
) where
import Prelude hiding (null)
import Data.Bits
import Data.Binary
import Control.Monad
import Data.Set.TernarySet.Internal
-- | Quickly build a tree without an initial tree. This should be used
-- to create an initial tree, using insert there after.
singleton :: Ord a => [a] -> TernarySet a
singleton (x:xs) = Node x End (singleton xs) End
singleton [] = Null End
-- | Inserts an entries into a tree.
insert :: Ord a => [a] -> TernarySet a -> TernarySet a
insert xss@(_:_) End = singleton xss
insert xss@(_:_) (Null rest) = Null $ insert xss rest
insert [] End = Null End
insert [] (Node ele l e h) = Node ele (insert [] l) e h
insert [] (Null rest) = Null rest
insert xss@(x:xs) (Node ele l e h) =
case compare x ele of
LT -> Node ele (insert xss l) e h
EQ -> Node ele l (insert xs e) h
GT -> Node ele l e (insert xss h)
-- | Returns true if the `[a]` is in the TernarySet
member :: Ord a => [a] -> TernarySet a -> Bool
member _ End = False
member [] (Null _) = True
member [] (Node _ l _ _) = member [] l
member xss@(_:_) (Null rest) = member xss rest
member xss@(x:xs) (Node ele l e h) =
case compare x ele of
LT -> member xss l
EQ -> member xs e
GT -> member xss h
-- | Counts how many entries there are in the tree.
size :: TernarySet a -> Int
size End = 0
size (Null rest) = 1 + size rest
size (Node _ l e h) = size l + size e + size h
-- | Creates a new tree from a list of 'strings'
fromList :: Ord a => [[a]] -> TernarySet a
fromList = foldl (flip insert) empty
-- | Returns a (sorted) list of all elements inserted into the set.
elems :: TernarySet a -> [[a]]
elems End = []
elems (Null rest) = []:elems rest
elems (Node ele l e g) = elems l ++ (map (ele:) (elems e) ++ elems g)
-- | An empty set.
empty :: TernarySet a
empty = End
-- | Returns true if the set is empty.
null :: TernarySet a -> Bool
null End = True
null _ = False
-- instance Binary a => Binary (Elem a) where
-- put Null = putWord8 0
-- put (C x) = putWord8 1 >> put x
--
-- get = do
-- n <- getWord8
-- case n of
-- 0 -> return Null
-- 1 -> liftM C get
-- | This binary uses the fact that the number of Ends can be represented
-- in binary numbers to save a lot of space.
instance Binary a => Binary (TernarySet a) where
put (Node ch End End End) = do
putWord8 0
put ch
put (Node ch End End h) = do
putWord8 1
put ch
put h
put (Node ch End e End) = do
putWord8 2
put ch
put e
put (Node ch End e h) = do
putWord8 3
put ch
put e
put h
put (Node ch l End End) = do
putWord8 4
put ch
put l
put (Node ch l End h) = do
putWord8 5
put ch
put l
put h
put (Node ch l e End) = do
putWord8 6
put ch
put l
put e
-- General case
put (Node ch l e h) = do
putWord8 7
put ch
put l
put e
put h
put (Null End) = putWord8 8
put (Null rest) = do
putWord8 9
put rest
put End = putWord8 10
get = do
tag <- getWord8
case tag of
_ | tag < 8 ->
do
ch <- get
l <- if tag `testBit` 2 then get else return End
e <- if tag `testBit` 1 then get else return End
h <- if tag `testBit` 0 then get else return End
return (Node ch l e h)
8 -> return (Null End)
9 -> liftM Null get
10 -> return End
_ -> error ("Invalid data in binary stream. tag: " ++ show tag)