TernaryTrees 0.1.1.1 → 0.1.2.0
raw patch · 5 files changed
+88/−111 lines, 5 files
Files
- Data/Map/TernaryMap.hs +74/−102
- Data/Set/StringSet.hs +3/−1
- Data/Set/TernarySet.hs +3/−1
- Main.hs +4/−2
- TernaryTrees.cabal +4/−5
Data/Map/TernaryMap.hs view
@@ -9,191 +9,163 @@ import Data.Bits import Data.Binary import Control.Monad-import qualified Data.Set.TernarySet as S import Prelude hiding (lookup) --- | Elem2 a b is used to hold elements of a list after insertion, and--- indicate that we've reached the end of the list.-data Elem2 a b = C !a- | Val b- deriving (Show) -- | TernaryMap a b is ternary tree. It is commonly used for storing word lists -- like dictionaries.-data TernaryMap a b = TNode !(Elem2 a b) !(TernaryMap a b) !(TernaryMap a b) !(TernaryMap a b)- | TEnd+data TernaryMap a b = Node !a !(TernaryMap a b) !(TernaryMap a b) !(TernaryMap a b)+ | Null b !(TernaryMap a b)+ | End deriving (Show, Eq) --instance Eq a => Eq (Elem2 a b) where- (Val _) == (Val _) = True- (Val _) == x = False- x == (Val _) = False- (C a) == (C b) = a == b---- | All elements are greater than the Val Elem, otherwise they are--- ordered according to their own ord instance (for the `compare (C x) (C y)` case).-instance (Ord a) => Ord (Elem2 a b) where- compare (Val _) (Val _) = EQ- compare (Val _) x = LT- compare x (Val _) = GT- compare (C x) (C y) = compare x y--isVal (Val _) = True-isVal _ = False- -- | 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] -> b -> TernaryMap a b-singleton (x:xs) b = TNode (C x) TEnd (singleton xs b) TEnd-singleton [] b = TNode (Val b) TEnd TEnd TEnd+singleton (x:xs) b = Node x End (singleton xs b) End+singleton [] b = Null b End -- | Inserts an entrie into a tree. Values with the same key will be replaced -- with the newer value. insert :: Ord a => [a] -> b -> TernaryMap a b -> TernaryMap a b--- General case-insert xss@(x:xs) b (TNode ele l e h) =- case compare (C x) ele of- LT -> TNode ele (insert xss b l) e h- EQ -> TNode ele l (insert xs b e) h- GT -> TNode ele l e (insert xss b h)--- Insert new elements quickly-insert xss@(x:xs) b TEnd =- singleton xss b--- end of word in non empty tree-insert [] b (TNode ele l e h) = - case compare (Val b) ele of- EQ -> TNode (Val b) l e h- LT -> TNode ele (insert [] b l) e h--- end of word in empty tree-insert [] b TEnd =- TNode (Val b) TEnd TEnd TEnd+insert xss@(_:_) b End = singleton xss b+insert xss@(_:_) b (Null b' rest) = Null b' $ insert xss b rest+insert [] b End = Null b End+insert [] b (Node ele l e h) = Node ele (insert [] b l) e h+insert [] b (Null _ rest) = Null b rest+insert xss@(x:xs) b (Node ele l e h) =+ case compare x ele of+ LT -> Node ele (insert xss b l) e h+ EQ -> Node ele l (insert xs b e) h+ GT -> Node ele l e (insert xss b h) -- | Returns true if the `[a]` is a key in the TernaryMap. member :: Ord a => [a] -> TernaryMap a b -> Bool-member _ TEnd = False-member [] (TNode ele l e h) = isVal ele || member [] l-member xss@(x:xs) (TNode ele l e h) = - case compare (C x) ele of+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 + lookup :: Ord a => [a] -> TernaryMap a b -> Maybe b-lookup _ TEnd = Nothing-lookup [] (TNode (Val b) _ _ _) = Just b-lookup [] (TNode ele l _ _) = lookup [] l-lookup xss@(x:xs) (TNode ele l e h) =- case compare (C x) ele of+lookup _ End = Nothing+lookup [] (Null b _) = Just b+lookup [] (Node _ l _ _) = lookup [] l+lookup xs (Null _ rest) = lookup xs rest+lookup xss@(x:xs) (Node ele l e h) =+ case compare x ele of LT -> lookup xss l EQ -> lookup xs e GT -> lookup xss h+ (!) :: Ord a => TernaryMap a b -> [a] -> Maybe b (!) = flip lookup -- | Returns the number of non-Val Elems. not exported treeSize :: TernaryMap a b -> Int-treeSize TEnd = 0-treeSize (TNode (Val _) l e h) = treeSize l + treeSize e + treeSize h-treeSize (TNode _ l e h) = 1 + treeSize l + treeSize e + treeSize h+treeSize End = 0+treeSize (Node _ l e h) = 1 + treeSize l + treeSize e + treeSize h+treeSize (Null _ rest) = treeSize rest -- | Counts how many entries there are in the tree. size :: TernaryMap a b -> Int-size TEnd = 0-size (TNode (Val _) l _ h) = 1 + size l + size h-size (TNode _ l e h) = size l + size e + size h+size End = 0+size (Node _ l e h) = size l + size e + size h+size (Null _ rest) = 1 + size rest -- | Creates a new tree from a list of 'strings' fromList :: Ord a => [([a],b)] -> TernaryMap a b-fromList = foldl (\tree (as,b) -> insert as b tree) TEnd+fromList = foldl (\tree (as,b) -> insert as b tree) empty -- | An empty map. empty :: TernaryMap a b-empty = TEnd+empty = End -- | Makes a list of all the values in the map. elems :: TernaryMap a b -> [b]-elems (TEnd) = []-elems (TNode (Val v) l _ h) = elems l ++ (v : elems h)-elems (TNode _ l e h) = elems l ++ (elems e ++ elems h)+elems End = []+elems (Node _ l e h) = elems l ++ (elems e ++ elems h)+elems (Null b rest) = b : elems rest -- | Returns true if the map is empty. null :: TernaryMap a b -> Bool-null TEnd = True-null _ = False+null End = True+null _ = False -- keySet :: TernaryMap a b -> S.TernarySet a--- keySet TEnd = S.TEnd--- keySet (TNode (C x) l e h) = S.TNode (S.C x) (keySet l) (keySet e) (keySet h)--- keySet (TNode (Val _) l e h) = S.TNode (S.Null) (keySet l) (keySet e) (keySet h)+-- keySet End = S.End+-- keySet (Node (C x) l e h) = S.Node (S.C x) (keySet l) (keySet e) (keySet h)+-- keySet (Node (Val _) l e h) = S.Node (S.Null) (keySet l) (keySet e) (keySet h) -instance Functor (Elem2 a) where- fmap _ (C x) = C x- fmap f (Val b) = Val . f $ b instance Functor (TernaryMap a) where- fmap f (TNode ele l e h) = TNode (fmap f ele) (fmap f l) (fmap f e) (fmap f h)- fmap _ TEnd = TEnd--instance (Binary a, Binary b) => Binary (Elem2 a b) where- put (C a) = putWord8 0 >> put a- put (Val b) = putWord8 1 >> put b- get = do- n <- getWord8- case n of- 0 -> liftM C get- 1 -> liftM Val get+ fmap _ End = End+ fmap f (Null b rest) = Null (f b) (fmap f rest)+ fmap f (Node ele l e h) = Node ele (fmap f l) (fmap f e) (fmap f h) -- | A rather long Binary instance, that uses binary numbers to indicate--- where TEnds are efficiently.+-- where Ends are efficiently. instance (Binary a, Binary b) => Binary (TernaryMap a b) where- put (TNode ch TEnd TEnd TEnd) = do+ put (Node ch End End End) = do putWord8 0 put ch- put (TNode ch TEnd TEnd h) = do+ put (Node ch End End h) = do putWord8 1 put ch put h- put (TNode ch TEnd e TEnd) = do+ put (Node ch End e End) = do putWord8 2 put ch put e- put (TNode ch TEnd e h) = do+ put (Node ch End e h) = do putWord8 3 put ch put e put h- put (TNode ch l TEnd TEnd) = do+ put (Node ch l End End) = do putWord8 4 put ch put l- put (TNode ch l TEnd h) = do+ put (Node ch l End h) = do putWord8 5 put ch put l put h- put (TNode ch l e TEnd) = do+ put (Node ch l e End) = do putWord8 6 put ch put l put e -- General case- put (TNode ch l e h) = do+ put (Node ch l e h) = do putWord8 7 put ch put l put e put h- put TEnd = putWord8 8+ put (Null b End) = putWord8 8 >> put b+ put (Null b rest) = do+ putWord8 9+ put b+ put rest+ put End = putWord8 10 get = do tag <- getWord8- if tag < 8- then do- ch <- get- l <- if (tag `testBit` 2) then get else return TEnd- e <- if (tag `testBit` 1) then get else return TEnd- h <- if (tag `testBit` 0) then get else return TEnd- return (TNode ch l e h)- else return TEnd+ 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 -> liftM (flip Null End) get+ 9 -> liftM2 Null get get+ _ -> return End
Data/Set/StringSet.hs view
@@ -113,10 +113,11 @@ put l put e put h- put End = putWord8 8+ put (Null End) = putWord8 8 put (Null rest) = do putWord8 9 put rest+ put End = putWord8 10 get = do tag <- getWord8@@ -128,6 +129,7 @@ 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 _ -> return End
Data/Set/TernarySet.hs view
@@ -153,10 +153,11 @@ put l put e put h- put End = putWord8 8+ put (Null End) = putWord8 8 put (Null rest) = do putWord8 9 put rest+ put End = putWord8 10 get = do tag <- getWord8@@ -168,6 +169,7 @@ 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 _ -> return End
Main.hs view
@@ -3,6 +3,7 @@ import Data.Binary -- import Data.Set.TernarySet import Data.Set.StringSet+-- import Data.Set import System.IO import System.Environment @@ -30,8 +31,9 @@ putStr "done.\nRead in data matches original: " print (tree == ntree) -- check the read in tree is the same as the one we wrote -- - -- putStrLn "\n-- Enter a word to see if it is in the dictionary (^C to exit):"- -- interact' (("-- " ++) . show . (`isElem` tree)) -- enter a word to see if it's in the tree+ -- Comment out these lines for benchmarking.+ putStrLn "\n-- Enter a word to see if it is in the dictionary (^C to exit):"+ interact' ((++ "\n> ") . ("-- " ++) . show . (`member` tree)) -- enter a word to see if it's in the tree interact' :: (String -> String) -> IO () interact' f = do
TernaryTrees.cabal view
@@ -1,5 +1,5 @@ Name: TernaryTrees-Version: 0.1.1.1+Version: 0.1.2.0 Category: Data Structures Synopsis: Efficient pure ternary tree Sets and Maps Description: Ternary trees are an efficient structure often used for storing@@ -20,12 +20,11 @@ . New in this version: .- * Refactored a lot of the datatypes for the Sets (much of their code is- exactly the same now)+ * Changed TernaryMap to match the Set implementations more. .- * Made the get implementation shorter and clearer (thanks to olsner on IRC)+ * Changed the Data.Binary instance again, hopefully it'll remain more stable from here on. .- * There is now a darcs repo: <http://random.axman6.com/darcs/TernaryTrees/>+ * Changed the tdict source to actually do what i said it would, by actually asking the user for input. . © 2009 by Alex Mason (<http://random.axman6.com/blog/>). BSD3 license.