packages feed

pred-trie 0.0.1 → 0.0.2

raw patch · 7 files changed

+287/−105 lines, 7 filesdep +criteriondep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: criterion

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.Trie.Pred: [More] :: t -> Maybe x -> NonEmpty (PredTrie p t x) -> PredTrie p t x
- Data.Trie.Pred: [Pred] :: p -> (t -> Maybe r) -> Maybe (r -> x) -> [PredTrie p t (r -> x)] -> PredTrie p t x
- Data.Trie.Pred: [Rest] :: NonEmpty t -> x -> PredTrie p t x
- Data.Trie.Pred: areDisjoint :: (Eq t, Eq p) => PredTrie p t x -> PredTrie p t x -> Bool
- Data.Trie.Pred: data PredTrie p t x
- Data.Trie.Pred: lookup :: Eq t => NonEmpty t -> PredTrie p t x -> Maybe x
- Data.Trie.Pred: merge :: (Eq t, Eq p) => PredTrie p t x -> PredTrie p t x -> PredTrie p t x
+ Data.Trie.Pred.Unified: [Rooted] :: (Maybe x) -> [NUPTrie t x] -> RPTrie t x
+ Data.Trie.Pred.Unified: data RPTrie t x
+ Data.Trie.Pred.Unified: instance Eq t => Monoid (RPTrie t x)
+ Data.Trie.Pred.Unified: merge :: (Eq t) => RPTrie t x -> RPTrie t x -> RPTrie t x
+ Data.Trie.Pred.Unified.Fast: [FUMore] :: t -> Maybe x -> NonEmpty (FUPTrie t x) -> FUPTrie t x
+ Data.Trie.Pred.Unified.Fast: [FUPred] :: t -> (t -> Maybe r) -> Maybe (r -> x) -> [FUPTrie t (r -> x)] -> FUPTrie t x
+ Data.Trie.Pred.Unified.Fast: [FURest] :: NonEmpty t -> x -> FUPTrie t x
+ Data.Trie.Pred.Unified.Fast: areDisjoint :: (Eq t) => FUPTrie t x -> FUPTrie t x -> Bool
+ Data.Trie.Pred.Unified.Fast: data FUPTrie t x
+ Data.Trie.Pred.Unified.Fast: lookup :: Eq t => NonEmpty t -> FUPTrie t x -> Maybe x
+ Data.Trie.Pred.Unified.Fast: merge :: (Eq t) => FUPTrie t x -> FUPTrie t x -> FUPTrie t x
+ Data.Trie.Pred.Unified.Norm: [NUMore] :: t -> Maybe x -> [NUPTrie t x] -> NUPTrie t x
+ Data.Trie.Pred.Unified.Norm: [NUPred] :: t -> (t -> Maybe r) -> Maybe (r -> x) -> [NUPTrie t (r -> x)] -> NUPTrie t x
+ Data.Trie.Pred.Unified.Norm: areDisjoint :: (Eq t) => NUPTrie t x -> NUPTrie t x -> Bool
+ Data.Trie.Pred.Unified.Norm: data NUPTrie t x
+ Data.Trie.Pred.Unified.Norm: lookup :: Eq t => NonEmpty t -> NUPTrie t x -> Maybe x
+ Data.Trie.Pred.Unified.Norm: merge :: (Eq t) => NUPTrie t x -> NUPTrie t x -> NUPTrie t x

Files

+ bench/SimpleVShort.hs view
@@ -0,0 +1,64 @@+module Main where+++import           Data.Trie.Pred.FastUnified+import qualified Data.Trie.Pred.FastUnified as FU+import           Data.Trie.Pred.NormUnified+import qualified Data.Trie.Pred.NormUnified as NU+import Criterion.Main+import           Data.List.NonEmpty+import qualified Data.List.NonEmpty as NE+++tdFU = FUMore "foo" Nothing $ NE.fromList+         [ FURest ("bar":|["baz","qux"]) 1+         , FUMore "tro" (Just 2) $ NE.fromList+             [ FUMore "zja" (Just 3) $ NE.fromList+                 [ FURest ("hda":|["jes","kuq"]) 4 ]+             , FURest ("end":|["orp","vag"]) 5+             ]+         , FURest ("dic":|["but","gea"]) 6+         ]++tdNU = NUMore "foo" Nothing+         [ NUMore "bar" Nothing+             [ NUMore "baz" Nothing+                 [ NUMore "qux" (Just 1) []+                 ]+             ]+         , NUMore "tro" (Just 2)+             [ NUMore "zja" (Just 3)+                 [ NUMore "hda" Nothing+                     [ NUMore "jes" Nothing+                         [ NUMore "kuq" (Just 4) []+                         ]+                     ]+                 ]+             , NUMore "end" Nothing+                 [ NUMore "orp" Nothing+                     [ NUMore "vag" (Just 5) []+                     ]+                 ]+             ]+         , NUMore "dic" Nothing+             [ NUMore "but" Nothing+                 [ NUMore "gea" (Just 6) []+                 ]+             ]+         ]++++main = defaultMain+  [ bgroup "Fast" [ bench "foobarbaz"       $ whnf (FU.lookup $ "foo":|["bar","baz"]) tdFU+                  , bench "footrozjahdajes" $ whnf (FU.lookup $ "foo":|["tro","zja","hda","jes"]) tdFU+                  , bench "footroendorpvag" $ whnf (FU.lookup $ "foo":|["tro","end","orp","vag"]) tdFU+                  , bench "foodicbutgea"    $ whnf (FU.lookup $ "foo":|["dic","but","gea"]) tdFU+                  ]++  , bgroup "Norm" [ bench "foobarbaz"       $ whnf (NU.lookup $ "foo":|["bar","baz"]) tdNU+                  , bench "footrozjahdajes" $ whnf (NU.lookup $ "foo":|["tro","zja","hda","jes"]) tdNU+                  , bench "footroendorpvag" $ whnf (NU.lookup $ "foo":|["tro","end","orp","vag"]) tdNU+                  , bench "foodicbutgea"    $ whnf (NU.lookup $ "foo":|["dic","but","gea"]) tdNU+                  ]+  ]
pred-trie.cabal view
@@ -1,5 +1,5 @@ Name:                   pred-trie-Version:                0.0.1+Version:                0.0.2 Author:                 Athan Clark <athan.clark@gmail.com> Maintainer:             Athan Clark <athan.clark@gmail.com> License:                BSD3@@ -13,8 +13,9 @@   Default-Language:     Haskell2010   HS-Source-Dirs:       src   GHC-Options:          -Wall-  Exposed-Modules:      Data.Trie.Pred-  Other-Modules:        Data.Trie.Pred.Internal+  Exposed-Modules:      Data.Trie.Pred.Unified+                        Data.Trie.Pred.Unified.Fast+                        Data.Trie.Pred.Unified.Norm   Build-Depends:        base >= 4 && < 5                       , semigroups @@ -29,6 +30,15 @@                       , hspec                       , QuickCheck                       , quickcheck-instances++Benchmark simplevshort+    Type:               exitcode-stdio-1.0+    Main-Is:            SimpleVShort.hs+    HS-Source-Dirs:     bench+                      , src+    Build-Depends:      base+                      , criterion+                      , semigroups  Source-Repository head   Type:                 git
− src/Data/Trie/Pred.hs
@@ -1,99 +0,0 @@-{-# LANGUAGE-  GADTs-  #-}--module Data.Trie.Pred-  ( PredTrie (..)-  , lookup-  , merge-  , areDisjoint-  ) where--import Data.Trie.Pred.Internal--import Prelude hiding (lookup)-import Data.List.NonEmpty hiding (map)-import Data.List.NonEmpty as NE hiding (map)----- | A predicative trie is composed of explicit predicate labels (for equality--- tests of predicates), a type for node labels, and some content type-data PredTrie p t x where-  Rest :: NonEmpty t-       -> x-       -> PredTrie p t x-  More :: t-       -> Maybe x-       -> NonEmpty (PredTrie p t x)-       -> PredTrie p t x-  Pred :: p-       -> (t -> Maybe r)-       -> Maybe (r -> x)-       -> [PredTrie p t (r -> x)]-       -> PredTrie p t x----- | Overwrites when similar, leaves untouched when not-merge :: (Eq t, Eq p) => PredTrie p t x -> PredTrie p t x -> PredTrie p t x-merge xx@(Rest tss@(t:|ts) x) yy@(Rest pss@(p:|ps) y)-  | tss == pss = yy-  | t == p     = let-                   xx' = Rest (NE.fromList ts) x-                   yy' = Rest (NE.fromList ps) y-                 in-                 More p Nothing $-                   if areDisjoint xx' yy'-                     then NE.fromList [xx', yy']-                     else NE.fromList-                            [merge (Rest (NE.fromList ts) x) (Rest (NE.fromList ps) y)]-  | otherwise = xx-merge xx@(More t mx xs) yy@(More p my ys)-  | t == p = More p my $ NE.fromList $ foldr go [] $ (NE.toList xs) ++ (NE.toList ys)-  | otherwise = xx-  where-    go :: (Eq t, Eq p) => PredTrie p t x -> [PredTrie p t x] -> [PredTrie p t x]-    go a [] = [a]-    go a (b:bs) | areDisjoint a b =       a : b : bs-                | otherwise       = (merge a b) : bs-merge xx@(Pred t q mrx xrs) yy@(Pred p w mry yrs)-  | t == p = yy-  | otherwise = xx-merge xx@(Rest (t:|ts) x) yy@(More p my ys)-  | t == p = case ts of-               [] -> More p (Just x) ys-               _  -> More p my $ fmap (merge $ Rest (NE.fromList ts) x) ys-  | otherwise = xx-merge xx@(More t mx xs) yy@(Rest (p:|ps) y)-  | t == p = case ps of-               [] -> More t (Just y) xs-               _  -> More t mx $ fmap (flip merge $ Rest (NE.fromList ps) y) xs-  | otherwise = yy-merge xx yy@(Pred _ _ _ _) = yy -- Predicates are more general-merge xx@(Pred _ _ _ _) yy = xx---areDisjoint :: (Eq t, Eq p) => PredTrie p t x -> PredTrie p t x -> Bool-areDisjoint (Rest (t:|_) _) (Rest (p:|_) _) = t == p-areDisjoint (More t _ _)    (More p _ _)    = t == p-areDisjoint (Pred t _ _ _)  (Pred p _ _ _)  = t == p---lookup :: Eq t => NonEmpty t -> PredTrie p t x -> Maybe x-lookup tss@(t:|ts) (Rest ps x) | tss == ps = Just x-                               | otherwise = Nothing-lookup     (t:|ts) (More t' mx xs) | t == t' =-  case ts of-    [] -> mx-    _  -> getFirst $ NE.toList $ fmap (lookup $ NE.fromList ts) xs-                                   | otherwise = Nothing-lookup     (t:|ts) (Pred _ p mrx xrs) =-  p t >>=-    \r -> case ts of-      [] -> ($ r) <$> mrx-      _  -> ($ r) <$> (getFirst $ map (lookup $ NE.fromList ts) xrs)---getFirst :: [Maybe a] -> Maybe a-getFirst [] = Nothing-getFirst (Nothing:xs) = getFirst xs-getFirst (Just x :xs) = Just x
− src/Data/Trie/Pred/Internal.hs
@@ -1,3 +0,0 @@-module Data.Trie.Pred.Internal-    (-    ) where
+ src/Data/Trie/Pred/Unified.hs view
@@ -0,0 +1,21 @@+module Data.Trie.Pred.Unified where++import Data.Trie.Pred.Unified.Norm+import qualified Data.Trie.Pred.Unified.Norm as NU+import Data.Monoid+++data RPTrie t x = Rooted (Maybe x) [NUPTrie t x]++instance (Eq t) => Monoid (RPTrie t x) where+  mempty = Rooted Nothing []+  mappend = Data.Trie.Pred.Unified.merge++merge :: (Eq t) => RPTrie t x -> RPTrie t x -> RPTrie t x+merge (Rooted mx xs) (Rooted my ys) =+  Rooted my $ foldr go [] $ xs ++ ys+  where+    go :: (Eq t) => NUPTrie t x -> [NUPTrie t x] -> [NUPTrie t x]+    go a [] = [a]+    go a (b:bs) | NU.areDisjoint a b =          a : b : bs+                | otherwise          = (NU.merge a b) : bs
+ src/Data/Trie/Pred/Unified/Fast.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE+  GADTs+  #-}++module Data.Trie.Pred.Unified.Fast+  ( FUPTrie (..)+  , lookup+  , merge+  , areDisjoint+  ) where++import Prelude hiding (lookup)+import Data.List.NonEmpty hiding (map)+import Data.List.NonEmpty as NE hiding (map)++++-- | A fast, unified, predicative trie. Singleton, leaf-ending+-- branches have their own data constructor, predicate labels and literals+-- have a unified type.+data FUPTrie t x where+  FURest :: NonEmpty t+         -> x+         -> FUPTrie t x+  FUMore :: t+         -> Maybe x+         -> NonEmpty (FUPTrie t x)+         -> FUPTrie t x+  FUPred :: t+         -> (t -> Maybe r)+         -> Maybe (r -> x)+         -> [FUPTrie t (r -> x)]+         -> FUPTrie t x+++-- | Overwrites when similar, leaves untouched when not+merge :: (Eq t) => FUPTrie t x -> FUPTrie t x -> FUPTrie t x+merge xx@(FURest tss@(t:|ts) x) yy@(FURest pss@(p:|ps) y)+  | tss == pss = yy+  | t == p     = let+                   xx' = FURest (NE.fromList ts) x+                   yy' = FURest (NE.fromList ps) y+                 in+                 FUMore p Nothing $+                   if areDisjoint xx' yy'+                     then NE.fromList [xx', yy']+                     else NE.fromList+                            [merge (FURest (NE.fromList ts) x) (FURest (NE.fromList ps) y)]+  | otherwise = xx+merge xx@(FUMore t mx xs) yy@(FUMore p my ys)+  | t == p = FUMore p my $ NE.fromList $ foldr go [] $ (NE.toList xs) ++ (NE.toList ys)+  | otherwise = xx+  where+    go :: (Eq t) => FUPTrie t x -> [FUPTrie t x] -> [FUPTrie t x]+    go a [] = [a]+    go a (b:bs) | areDisjoint a b =       a : b : bs+                | otherwise       = (merge a b) : bs+merge xx@(FUPred t q mrx xrs) yy@(FUPred p w mry yrs)+  | t == p = yy+  | otherwise = xx+merge xx@(FURest (t:|ts) x) yy@(FUMore p my ys)+  | t == p = case ts of+               [] -> FUMore p (Just x) ys+               _  -> FUMore p my $ fmap (merge $ FURest (NE.fromList ts) x) ys+  | otherwise = xx+merge xx@(FUMore t mx xs) yy@(FURest (p:|ps) y)+  | t == p = case ps of+               [] -> FUMore t (Just y) xs+               _  -> FUMore t mx $ fmap (flip merge $ FURest (NE.fromList ps) y) xs+  | otherwise = yy+merge xx@(FUMore t mx xs) yy@(FUPred p w mrx xrs)+  | t == p = yy -- predicate children are incompatible+  | otherwise = xx+merge xx@(FURest (t:|ts) x) yy@(FUPred p w mry yrs)+  | t == p = yy+  | otherwise = xx+merge xx@(FUPred t q mrx xrs) yy@(FUMore p my ys)+  | t == p = yy+  | otherwise = xx+merge xx@(FUPred t q mrx xrs) yy@(FURest (p:|ps) y)+  | t == p = yy+  | otherwise = xx+++areDisjoint :: (Eq t) => FUPTrie t x -> FUPTrie t x -> Bool+areDisjoint (FURest (t:|_) _) (FURest (p:|_) _) = t == p+areDisjoint (FUMore t _ _)    (FUMore p _ _)    = t == p+areDisjoint (FURest (t:|_) _) (FUMore p _ _)    = t == p+areDisjoint (FUMore t _ _)    (FURest (p:|_) _) = t == p+areDisjoint (FUPred t _ _ _)  (FUPred p _ _ _)  = t == p+areDisjoint (FUPred t _ _ _)  (FUMore p _ _)    = t == p+areDisjoint (FUPred t _ _ _)  (FURest (p:|_) _) = t == p+areDisjoint (FUMore t _ _)    (FUPred p _ _ _)  = t == p+areDisjoint (FURest (t:|_) _) (FUPred p _ _ _)  = t == p+++lookup :: Eq t => NonEmpty t -> FUPTrie t x -> Maybe x+lookup tss@(t:|ts) (FURest ps x) | tss == ps = Just x+                                 | otherwise = Nothing+lookup     (t:|ts) (FUMore t' mx xs) | t == t' =+  case ts of+    [] -> mx+    _  -> getFirst $ NE.toList $ fmap (lookup $ NE.fromList ts) xs+                                   | otherwise = Nothing+lookup     (t:|ts) (FUPred _ p mrx xrs) =+  p t >>=+    \r -> case ts of+      [] -> ($ r) <$> mrx+      _  -> ($ r) <$> (getFirst $ map (lookup $ NE.fromList ts) xrs)+++getFirst :: [Maybe a] -> Maybe a+getFirst [] = Nothing+getFirst (Nothing:xs) = getFirst xs+getFirst (Just x :xs) = Just x
+ src/Data/Trie/Pred/Unified/Norm.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE+  GADTs+  #-}++module Data.Trie.Pred.Unified.Norm+  ( NUPTrie (..)+  , lookup+  , merge+  , areDisjoint+  ) where++import Prelude hiding (lookup)+import Data.List.NonEmpty hiding (map)+import Data.List.NonEmpty as NE hiding (map)++++data NUPTrie t x where+  NUMore :: t+         -> Maybe x+         -> [NUPTrie t x]+         -> NUPTrie t x+  NUPred :: t+         -> (t -> Maybe r)+         -> Maybe (r -> x)+         -> [NUPTrie t (r -> x)]+         -> NUPTrie t x+++-- | Overwrites when similar, leaves untouched when not+merge :: (Eq t) => NUPTrie t x -> NUPTrie t x -> NUPTrie t x+merge xx@(NUMore t mx xs) yy@(NUMore p my ys)+  | t == p = NUMore p my $ foldr go [] $ xs ++ ys+  | otherwise = xx+  where+    go :: (Eq t) => NUPTrie t x -> [NUPTrie t x] -> [NUPTrie t x]+    go a [] = [a]+    go a (b:bs) | areDisjoint a b =       a : b : bs+                | otherwise       = (merge a b) : bs+merge xx@(NUPred t q mrx xrs) yy@(NUPred p w mry yrs)+  | t == p = yy+  | otherwise = xx+merge xx@(NUMore t mx xs) yy@(NUPred p w mrx xrs)+  | t == p = yy -- predicate children are incompatible+  | otherwise = xx+merge xx@(NUPred t q mrx xrs) yy@(NUMore p my ys)+  | t == p = yy+  | otherwise = xx+++areDisjoint :: (Eq t) => NUPTrie t x -> NUPTrie t x -> Bool+areDisjoint (NUMore t _ _)    (NUMore p _ _)    = t == p+areDisjoint (NUPred t _ _ _)  (NUPred p _ _ _)  = t == p+areDisjoint (NUPred t _ _ _)  (NUMore p _ _)    = t == p+areDisjoint (NUMore t _ _)    (NUPred p _ _ _)  = t == p+++lookup :: Eq t => NonEmpty t -> NUPTrie t x -> Maybe x+lookup (t:|ts) (NUMore t' mx xs)+  | t == t' = case ts of+    [] -> mx+    _  -> getFirst $ map (lookup $ NE.fromList ts) xs+  | otherwise = Nothing+lookup (t:|ts) (NUPred _ p mrx xrs) =+  p t >>=+    \r -> case ts of+      [] -> ($ r) <$> mrx+      _  -> ($ r) <$> (getFirst $ map (lookup $ NE.fromList ts) xrs)+++getFirst :: [Maybe a] -> Maybe a+getFirst [] = Nothing+getFirst (Nothing:xs) = getFirst xs+getFirst (Just x :xs) = Just x