packages feed

pred-trie 0.5.1.2 → 0.6.0

raw patch · 10 files changed

+343/−662 lines, 10 filesdep +pred-triedep +strictdep −composition-extradep −quickcheck-instancesdep ~QuickCheckdep ~basedep ~poly-arityPVP ok

version bump matches the API change (PVP)

Dependencies added: pred-trie, strict

Dependencies removed: composition-extra, quickcheck-instances

Dependency ranges changed: QuickCheck, base, poly-arity, tries

API changes (from Hackage documentation)

- Data.Trie.Pred.Base: instance (GHC.Show.Show k, GHC.Show.Show a) => GHC.Show.Show (Data.Trie.Pred.Base.PredTrie k a)
- Data.Trie.Pred.Base.Step: PredSteps :: [PredStep k c s a] -> PredSteps k c s a
- Data.Trie.Pred.Base.Step: [predTag] :: PredStep k c s a -> !k
- Data.Trie.Pred.Base.Step: data PredStep k c s a
- Data.Trie.Pred.Base.Step: instance (GHC.Classes.Eq s, GHC.Classes.Eq k) => GHC.Base.Monoid (Data.Trie.Pred.Base.Step.PredSteps k c s a)
- Data.Trie.Pred.Base.Step: instance (GHC.Show.Show k, GHC.Show.Show s) => GHC.Show.Show (Data.Trie.Pred.Base.Step.PredSteps k c s a)
- Data.Trie.Pred.Base.Step: instance (GHC.Show.Show s, GHC.Show.Show k) => GHC.Show.Show (Data.Trie.Pred.Base.Step.PredStep k c s a)
- Data.Trie.Pred.Base.Step: instance Data.Trie.Class.Trie Data.List.NonEmpty.NonEmpty s c => Data.Trie.Class.Trie Data.List.NonEmpty.NonEmpty s (Data.Trie.Pred.Base.Step.PredSteps k c)
- Data.Trie.Pred.Base.Step: instance GHC.Base.Functor (c s) => GHC.Base.Functor (Data.Trie.Pred.Base.Step.PredSteps k c s)
- Data.Trie.Pred.Base.Step: newtype PredSteps k c s a
- Data.Trie.Pred.Mutable: HashTableTrie :: {-# UNPACK #-} !(HashTable s k (RawValue s k a)) -> [PredStep s k a] -> HashTableTrie s k a
- Data.Trie.Pred.Mutable: PredStep :: {-# UNPACK #-} !(PredKey s k a) -> !(Maybe (a -> r)) -> !(HashTableTrie s k (a -> r)) -> PredStep s k r
- Data.Trie.Pred.Mutable: RawValue :: !(Maybe a) -> !(HashTableTrie s k a) -> RawValue s k a
- Data.Trie.Pred.Mutable: RootedHashTableTrie :: !(Maybe a) -> !(HashTableTrie s k a) -> {-# UNPACK #-} !(PredSet s k) -> RootedHashTableTrie s k a
- Data.Trie.Pred.Mutable: [predData] :: PredStep s k r -> !(Maybe (a -> r))
- Data.Trie.Pred.Mutable: [predPred] :: PredStep s k r -> {-# UNPACK #-} !(PredKey s k a)
- Data.Trie.Pred.Mutable: [predPreds] :: HashTableTrie s k a -> [PredStep s k a]
- Data.Trie.Pred.Mutable: [predSub] :: PredStep s k r -> !(HashTableTrie s k (a -> r))
- Data.Trie.Pred.Mutable: [rawChildren] :: RawValue s k a -> !(HashTableTrie s k a)
- Data.Trie.Pred.Mutable: [rawValue] :: RawValue s k a -> !(Maybe a)
- Data.Trie.Pred.Mutable: [rawValues] :: HashTableTrie s k a -> {-# UNPACK #-} !(HashTable s k (RawValue s k a))
- Data.Trie.Pred.Mutable: [rootedBase] :: RootedHashTableTrie s k a -> !(Maybe a)
- Data.Trie.Pred.Mutable: [rootedPredSet] :: RootedHashTableTrie s k a -> {-# UNPACK #-} !(PredSet s k)
- Data.Trie.Pred.Mutable: [rootedSub] :: RootedHashTableTrie s k a -> !(HashTableTrie s k a)
- Data.Trie.Pred.Mutable: data HashTableTrie s k a
- Data.Trie.Pred.Mutable: data PredStep s k r
- Data.Trie.Pred.Mutable: data RawValue s k a
- Data.Trie.Pred.Mutable: data RootedHashTableTrie s k a
- Data.Trie.Pred.Mutable: insert :: (Eq k, Hashable k) => NonEmpty k -> a -> HashTableTrie s k a -> ST s (HashTableTrie s k a)
- Data.Trie.Pred.Mutable: lookup :: (Eq k, Hashable k, Typeable s, Typeable k) => PredSet s k -> NonEmpty k -> HashTableTrie s k a -> ST s (Maybe a)
- Data.Trie.Pred.Mutable: lookupR :: (Eq k, Hashable k, Typeable s, Typeable k, Typeable a) => [k] -> RootedHashTableTrie s k a -> ST s (Maybe a)
- Data.Trie.Pred.Mutable: match :: (Eq k, Hashable k, Typeable s, Typeable k) => PredSet s k -> NonEmpty k -> HashTableTrie s k a -> ST s (Maybe (NonEmpty k, a, [k]))
- Data.Trie.Pred.Mutable: matchR :: (Eq k, Hashable k, Typeable s, Typeable k, Typeable a) => [k] -> RootedHashTableTrie s k a -> ST s (Maybe ([k], a, [k]))
- Data.Trie.Pred.Mutable: matches :: (Eq k, Hashable k, Typeable s, Typeable k) => PredSet s k -> NonEmpty k -> HashTableTrie s k a -> ST s [(NonEmpty k, a, [k])]
- Data.Trie.Pred.Mutable: matchesR :: (Eq k, Hashable k, Typeable s, Typeable k, Typeable a) => [k] -> RootedHashTableTrie s k a -> ST s [([k], a, [k])]
- Data.Trie.Pred.Mutable: new :: ST s (HashTableTrie s k a)
- Data.Trie.Pred.Mutable: newR :: ST s (RootedHashTableTrie s k a)
- Data.Trie.Pred.Mutable.Morph: insertPredKey :: (Ord k', Typeable s, Typeable k, Typeable a) => k' -> PredKey s k a -> HMap k' -> HMap k'
- Data.Trie.Pred.Mutable.Morph: lookupPredKey :: (Ord k', Typeable s, Typeable k, Typeable a) => k' -> ST s (k -> Maybe a) -> HMap k' -> ST s (Maybe (PredKey s k a))
- Data.Trie.Pred.Mutable.Morph: toHashTable :: (Eq k, Hashable k) => HashMap k a -> ST s (HashTable s k a)
- Data.Trie.Pred.Mutable.Morph: toHashTableTrie :: (Eq k, Hashable k, Ord k, Typeable s, Typeable k, Typeable a) => STRef s (HMap k) -> PredSet s k -> PredTrie k a -> ST s (HashTableTrie s k a)
- Data.Trie.Pred.Mutable.Morph: toMutable :: (Eq k, Hashable k, Ord k, Typeable s, Typeable k, Typeable a) => PredSet s k -> PredTrie k a -> ST s (HashTableTrie s k a)
- Data.Trie.Pred.Mutable.Morph: toMutablePredStep :: (Ord k, Eq k, Hashable k, Typeable s, Typeable k, Typeable a) => STRef s (HMap k) -> PredSet s k -> PredStep k PredTrie k a -> ST s (PredStep s k a)
- Data.Trie.Pred.Mutable.Morph: toMutableRooted :: (Eq k, Hashable k, Ord k, Typeable s, Typeable k, Typeable a) => RootedPredTrie k a -> ST s (RootedHashTableTrie s k a)
- Data.Trie.Pred.Mutable.Morph: toRawValue :: (Eq k, Hashable k, Ord k, Typeable s, Typeable k, Typeable a) => STRef s (HMap k) -> PredSet s k -> HashMapChildren PredTrie k a -> ST s (RawValue s k a)
- Data.Trie.Pred.Mutable.Morph: type HMap k = Map k Dynamic
+ Data.Trie.Pred.Base: instance (Control.DeepSeq.NFData k, Control.DeepSeq.NFData a) => Control.DeepSeq.NFData (Data.Trie.Pred.Base.PredTrie k a)
+ Data.Trie.Pred.Base: instance (GHC.Show.Show a, GHC.Show.Show k) => GHC.Show.Show (Data.Trie.Pred.Base.PredTrie k a)
+ Data.Trie.Pred.Base.Step: Pred :: !(s -> Maybe r) -> !(Maybe (r -> a)) -> c s (r -> a) -> Pred c s a
+ Data.Trie.Pred.Base.Step: data Pred c s a
+ Data.Trie.Pred.Base.Step: instance (GHC.Base.Functor (c s), Control.DeepSeq.NFData (c s (s -> GHC.Base.Maybe a))) => Control.DeepSeq.NFData (Data.Trie.Pred.Base.Step.Pred c s a)
+ Data.Trie.Pred.Base.Step: instance (GHC.Base.Functor (c s), Control.DeepSeq.NFData (c s (s -> GHC.Base.Maybe a)), Control.DeepSeq.NFData k) => Control.DeepSeq.NFData (Data.Trie.Pred.Base.Step.PredStep k c s a)
+ Data.Trie.Pred.Base.Step: instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k) => GHC.Base.Monoid (Data.Trie.Pred.Base.Step.PredStep k c s a)
+ Data.Trie.Pred.Base.Step: instance Data.Trie.Class.Trie Data.List.NonEmpty.NonEmpty s c => Data.Trie.Class.Trie Data.List.NonEmpty.NonEmpty s (Data.Trie.Pred.Base.Step.Pred c)
+ Data.Trie.Pred.Base.Step: instance GHC.Base.Functor (c s) => GHC.Base.Functor (Data.Trie.Pred.Base.Step.Pred c s)
+ Data.Trie.Pred.Base.Step: instance GHC.Show.Show (Data.Trie.Pred.Base.Step.Pred c s a)
+ Data.Trie.Pred.Base.Step: instance GHC.Show.Show k => GHC.Show.Show (Data.Trie.Pred.Base.Step.PredStep k c s a)
+ Data.Trie.Pred.Base.Step: newtype PredStep k c s a
- Data.Trie.Pred.Base: PredTrie :: !(HashMapStep PredTrie k a) -> !(PredSteps k PredTrie k a) -> PredTrie k a
+ Data.Trie.Pred.Base: PredTrie :: !(HashMapStep PredTrie k a) -> PredStep k PredTrie k a -> PredTrie k a
- Data.Trie.Pred.Base: [predPreds] :: PredTrie k a -> !(PredSteps k PredTrie k a)
+ Data.Trie.Pred.Base: [predPreds] :: PredTrie k a -> PredStep k PredTrie k a
- Data.Trie.Pred.Base.Step: PredStep :: !k -> !(s -> Maybe r) -> !(Maybe (r -> a)) -> !(c s (r -> a)) -> PredStep k c s a
+ Data.Trie.Pred.Base.Step: PredStep :: HashMap k (Pred c s a) -> PredStep k c s a
- Data.Trie.Pred.Base.Step: [predData] :: PredStep k c s a -> !(Maybe (r -> a))
+ Data.Trie.Pred.Base.Step: [predData] :: Pred c s a -> !(Maybe (r -> a))
- Data.Trie.Pred.Base.Step: [predPred] :: PredStep k c s a -> !(s -> Maybe r)
+ Data.Trie.Pred.Base.Step: [predPred] :: Pred c s a -> !(s -> Maybe r)
- Data.Trie.Pred.Base.Step: [predSub] :: PredStep k c s a -> !(c s (r -> a))
+ Data.Trie.Pred.Base.Step: [predSub] :: Pred c s a -> c s (r -> a)
- Data.Trie.Pred.Base.Step: [unPredSteps] :: PredSteps k c s a -> [PredStep k c s a]
+ Data.Trie.Pred.Base.Step: [unPredSteps] :: PredStep k c s a -> HashMap k (Pred c s a)
- Data.Trie.Pred.Base.Step: singletonPred :: (Monoid (c s (r -> a)), Typeable r) => k -> (s -> Maybe r) -> (r -> a) -> PredStep k c s a
+ Data.Trie.Pred.Base.Step: singletonPred :: (Monoid (c s (r -> a)), Typeable r) => (s -> Maybe r) -> (r -> a) -> Pred c s a
- Data.Trie.Pred.Base.Step: unionPred :: (Eq k) => PredSteps k c s a -> PredSteps k c s a -> PredSteps k c s a
+ Data.Trie.Pred.Base.Step: unionPred :: (Eq k, Hashable k) => PredStep k c s a -> PredStep k c s a -> PredStep k c s a
- Data.Trie.Pred.Interface: only :: k -> PathChunk k Nothing
+ Data.Trie.Pred.Interface: only :: k -> PathChunk k 'Nothing
- Data.Trie.Pred.Interface: pred :: k -> (k -> Maybe r) -> PathChunk k (Just r)
+ Data.Trie.Pred.Interface: pred :: k -> (k -> Maybe r) -> PathChunk k ( 'Just r)
- Data.Trie.Pred.Interface.Types: only :: k -> PathChunk k Nothing
+ Data.Trie.Pred.Interface.Types: only :: k -> PathChunk k 'Nothing
- Data.Trie.Pred.Interface.Types: pred :: k -> (k -> Maybe r) -> PathChunk k (Just r)
+ Data.Trie.Pred.Interface.Types: pred :: k -> (k -> Maybe r) -> PathChunk k ( 'Just r)

Files

+ README.md view
@@ -0,0 +1,38 @@+pred-trie+=========++A predicative trie library - use predicates instead of literal match to capture+classes of results, instead of enumerating distinguished ones.++## Usage++The predicates are existentially quantified such that a predicate _creates_ an+unknown type, while it's result must have the _necessary arity_, matching the+quantified type, to fulfill the lookup:++```haskell+PredTrie s a+  = PNil+  | forall t. PCons+      { predicate :: s -> Maybe t+      , result    :: t -> a+      }+```++...basically.++I broke the lookup phases into "steps", like the [tries](https://github.com/athanclark/tries)+package, and used the fastest-lookup `HashMapStep` trie implementation for the+literal lookups. For more info, read the code :D++## How to run tests++```bash+stack test+```++## Benchmarking++```bash+stack bench --benchmark-arguments="--output profile.html"+```
− bench/Bench.hs
@@ -1,69 +0,0 @@-{-# LANGUAGE-    OverloadedStrings-  #-}--module Main where---import Prelude hiding (lookup)-import           Data.Trie.Pred.Base-import           Data.Trie.Pred.Base.Step (PredStep (..), PredSteps (..))-import           Data.Trie.Class-import           Data.Trie.HashMap (HashMapStep (..), HashMapChildren (..))-import qualified Data.HashMap.Lazy as HM-import           Data.List.NonEmpty-import qualified Data.List.NonEmpty as NE-import qualified Data.Text as T-import           Data.Attoparsec.Text-import           Criterion.Main-import           Data.Set.Class as Sets---doubleLit :: RootedPredTrie T.Text Double-doubleLit = RootedPredTrie Nothing $ PredTrie-              (HashMapStep $ unUnion $ foldMap (Union . genStep) [1..100])-              (PredSteps [])-  where-    genStep n = HM.singleton (T.pack $ show n) $-                  HashMapChildren (Just n) Nothing--doubleAtto :: RootedPredTrie T.Text Double-doubleAtto = RootedPredTrie Nothing $ PredTrie mempty $ PredSteps-  [PredStep "d" (eitherToMaybe . parseOnly double) (Just id) mempty]-  where-    eitherToMaybe (Left _) = Nothing-    eitherToMaybe (Right a) = Just a--deepLit :: RootedPredTrie T.Text Double-deepLit = RootedPredTrie Nothing $ go 10-  where-    go n | n == 0    = PredTrie (HashMapStep HM.empty) (PredSteps [])-         | otherwise = PredTrie (HashMapStep $ HM.singleton (T.pack $ show n) $-                                                 HashMapChildren (Just n) (Just . go $ n-1))-                                (PredSteps [])--main = defaultMain-  [ bgroup "Lit vs. Pred"-    [ bgroup "Lit"-      [ bench "1" $ whnf (lookup ["1"]) doubleLit-      , bench "2" $ whnf (lookup ["21"]) doubleLit-      , bench "3" $ whnf (lookup ["41"]) doubleLit-      , bench "4" $ whnf (lookup ["61"]) doubleLit-      , bench "4" $ whnf (lookup ["81"]) doubleLit-      ]-    , bgroup "Pred"-      [ bench "1" $ whnf (lookup ["1"]) doubleAtto-      , bench "2" $ whnf (lookup ["21"]) doubleAtto-      , bench "3" $ whnf (lookup ["41"]) doubleAtto-      , bench "4" $ whnf (lookup ["61"]) doubleAtto-      , bench "4" $ whnf (lookup ["81"]) doubleAtto-      ]-    ]-  , bgroup "Lit Deep"-    [ bench "10" $ whnf (lookup ["10"]) deepLit-    , bench "9" $ whnf (lookup ["10","9"]) deepLit-    , bench "8" $ whnf (lookup ["10","9","8"]) deepLit-    , bench "7" $ whnf (lookup ["10","9","8","7"]) deepLit-    , bench "6" $ whnf (lookup ["10","9","8","7","6"]) deepLit-    ]-  ]
+ bench/Main.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE+    OverloadedStrings+  #-}++module Main where+++import Prelude hiding (lookup)+import           Data.Trie.Pred.Base (PredTrie (..), RootedPredTrie (..))+import           Data.Trie.Pred.Base.Step (PredStep (..), Pred (..))+import           Data.Trie.Class (Trie (lookup, insert, delete))+import           Data.Trie.HashMap (HashMapStep (..), HashMapChildren (..))+import qualified Data.HashMap.Strict as HM+import           Data.List.NonEmpty ()+import qualified Data.List.NonEmpty as NE+import qualified Data.Text as T+import           Data.Attoparsec.Text (parseOnly, double)+import           Criterion.Main (defaultMain, whnf, bench, bgroup)+import           Data.Set.Class as Sets+++doubleLit :: RootedPredTrie T.Text Double+doubleLit = RootedPredTrie Nothing $ PredTrie+              (HashMapStep $ unUnion $ foldMap (Union . genStep) [1..100])+              (PredStep HM.empty)+  where+    genStep n = HM.singleton (T.pack $ show n) $+                  HashMapChildren (Just n) Nothing++doubleAtto :: RootedPredTrie T.Text Double+doubleAtto = RootedPredTrie Nothing $ PredTrie mempty $ PredStep $+  HM.singleton "d" $ Pred (eitherToMaybe . parseOnly double) (Just id) mempty+  where+    eitherToMaybe (Left _) = Nothing+    eitherToMaybe (Right a) = Just a++deepLit :: RootedPredTrie T.Text Double+deepLit = RootedPredTrie Nothing $ go 10+  where+    go n | n == 0    = PredTrie (HashMapStep HM.empty) (PredStep HM.empty)+         | otherwise = PredTrie (HashMapStep $ HM.singleton (T.pack $ show n) $+                                                 HashMapChildren (Just n) (Just . go $ n-1))+                                (PredStep HM.empty)++main = defaultMain+  [ bgroup "Lit vs. Pred"+    [ bgroup "Lit"+      [ bench "1" $ whnf (lookup ["1"]) doubleLit+      , bench "2" $ whnf (lookup ["21"]) doubleLit+      , bench "3" $ whnf (lookup ["41"]) doubleLit+      , bench "4" $ whnf (lookup ["61"]) doubleLit+      , bench "4" $ whnf (lookup ["81"]) doubleLit+      ]+    , bgroup "Pred"+      [ bench "1" $ whnf (lookup ["1"]) doubleAtto+      , bench "2" $ whnf (lookup ["21"]) doubleAtto+      , bench "3" $ whnf (lookup ["41"]) doubleAtto+      , bench "4" $ whnf (lookup ["61"]) doubleAtto+      , bench "4" $ whnf (lookup ["81"]) doubleAtto+      ]+    ]+  , bgroup "Lit Deep"+    [ bench "10" $ whnf (lookup ["10"]) deepLit+    , bench "9" $ whnf (lookup ["10","9"]) deepLit+    , bench "8" $ whnf (lookup ["10","9","8"]) deepLit+    , bench "7" $ whnf (lookup ["10","9","8","7"]) deepLit+    , bench "6" $ whnf (lookup ["10","9","8","7","6"]) deepLit+    ]+  ]
pred-trie.cabal view
@@ -1,97 +1,114 @@-Name:                   pred-trie-Version:                0.5.1.2-Author:                 Athan Clark <athan.clark@gmail.com>-Maintainer:             Athan Clark <athan.clark@gmail.com>-License:                BSD3-License-File:           LICENSE-Category:               Data-Synopsis:               Predicative tries--- Description:-Cabal-Version:          >= 1.10-Build-Type:             Simple+-- This file has been generated from package.yaml by hpack version 0.21.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: f26559f76aae89fad9fe87fd25894fb71ded746440ac54961b4e1a5837de40ea -Library-  Default-Language:     Haskell2010-  HS-Source-Dirs:       src-  GHC-Options:          -Wall-  Exposed-Modules:      Data.Trie.Pred-                        Data.Trie.Pred.Base-                        Data.Trie.Pred.Base.Step-                        Data.Trie.Pred.Interface-                        Data.Trie.Pred.Interface.Types-                        Data.Trie.Pred.Mutable-                        Data.Trie.Pred.Mutable.Morph-  Build-Depends:        base >= 4.8 && < 5-                      , composition-extra >= 2.0.0-                      , containers-                      , hashable-                      , hashtables-                      , mtl-                      , poly-arity >= 0.0.7-                      , pred-set-                      , semigroups-                      , tries >= 0.0.4-                      , unordered-containers-                      , QuickCheck >= 2.9.2+name:           pred-trie+version:        0.6.0+synopsis:       Predicative tries+description:    Please see the README on Github at <https://git.localcooking.com/tooling/pred-trie#readme>+category:       Data+author:         Athan Clark+maintainer:     athan.clark@localcooking.com+copyright:      2018 Athan Clark+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10 -Test-Suite spec-  Type:                 exitcode-stdio-1.0-  Default-Language:     Haskell2010-  Hs-Source-Dirs:       src-                      , test-  Ghc-Options:          -Wall -threaded-  Main-Is:              Spec.hs-  Other-Modules:        Data.Trie.PredSpec-                        Data.Trie.Pred-                        Data.Trie.Pred.Base-                        Data.Trie.Pred.Base.Step-                        Data.Trie.Pred.Interface-                        Data.Trie.Pred.Interface.Types-  Build-Depends:        base-                      , attoparsec-                      , composition-extra-                      , deepseq-                      , errors-                      , hashable-                      , mtl-                      , poly-arity-                      , semigroups-                      , text-                      , tries-                      , unordered-containers-                      , tasty-                      , tasty-quickcheck-                      , tasty-hunit-                      , QuickCheck-                      , quickcheck-instances+extra-source-files:+    README.md -Benchmark bench-  Type:                 exitcode-stdio-1.0-  Default-Language:     Haskell2010-  Main-Is:              Bench.hs-  Other-Modules:        Data.Trie.Pred-                        Data.Trie.Pred.Base-                        Data.Trie.Pred.Base.Step-                        Data.Trie.Pred.Interface-                        Data.Trie.Pred.Interface.Types-  HS-Source-Dirs:       bench-                      , src-  Ghc-Options:          -Wall -threaded-  Build-Depends:        base-                      , attoparsec-                      , composition-extra-                      , deepseq-                      , hashable-                      , mtl-                      , poly-arity-                      , semigroups-                      , text-                      , tries-                      , unordered-containers-                      , QuickCheck-                      , sets-                      , criterion+source-repository head+  type: git+  location: git://git.localcooking.com/tooling/pred-trie.git -Source-Repository head-  Type:                 git-  Location:             https://github.com/athanclark/pred-trie.git+library+  exposed-modules:+      Data.Trie.Pred+      Data.Trie.Pred.Base+      Data.Trie.Pred.Base.Step+      Data.Trie.Pred.Interface+      Data.Trie.Pred.Interface.Types+  other-modules:+      Paths_pred_trie+  hs-source-dirs:+      src+  ghc-options: -Wall+  build-depends:+      QuickCheck >=2.9.2+    , base >=4.8 && <5.0+    , containers+    , deepseq+    , hashable+    , hashtables+    , mtl+    , poly-arity >=0.0.7+    , pred-set+    , semigroups+    , strict+    , tries >=0.0.5+    , unordered-containers+  default-language: Haskell2010++test-suite pred-trie-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Data.Trie.PredSpec+      Paths_pred_trie+  hs-source-dirs:+      test+  ghc-options: -Wall -threaded -rtsopts -Wall -with-rtsopts=-N+  build-depends:+      QuickCheck >=2.9.2+    , attoparsec+    , base+    , containers+    , deepseq+    , errors+    , hashable+    , hashtables+    , mtl+    , poly-arity >=0.0.7+    , pred-set+    , pred-trie+    , semigroups+    , strict+    , tasty+    , tasty-hunit+    , tasty-quickcheck+    , text+    , tries >=0.0.5+    , unordered-containers+  default-language: Haskell2010++benchmark pred-trie-bench+  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:+      Paths_pred_trie+  hs-source-dirs:+      bench+  ghc-options: -Wall -threaded -rtsopts -Wall -with-rtsopts=-N+  build-depends:+      QuickCheck >=2.9.2+    , attoparsec+    , base+    , containers+    , criterion+    , deepseq+    , hashable+    , hashtables+    , mtl+    , poly-arity >=0.0.7+    , pred-set+    , pred-trie+    , semigroups+    , sets+    , strict+    , text+    , tries >=0.0.5+    , unordered-containers+  default-language: Haskell2010
src/Data/Trie/Pred/Base.hs view
@@ -63,19 +63,20 @@ module Data.Trie.Pred.Base where  import Prelude hiding (lookup)-import Data.Trie.Pred.Base.Step-import Data.Trie.Class+import Data.Trie.Pred.Base.Step (PredStep (..), Pred (..))+import Data.Trie.Class (Trie (..)) import qualified Data.Trie.HashMap as HT import qualified Data.HashMap.Lazy as HM import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE -import Data.Typeable-import Data.Functor.Syntax-import Data.Monoid+import Data.Data (Typeable)+import Data.Monoid (First (..), Last (..), (<>)) import Data.Maybe (fromMaybe)-import Data.Hashable-import Test.QuickCheck+import Data.Hashable (Hashable)+import qualified Data.HashMap.Strict as HMS+import Test.QuickCheck (Arbitrary (..))+import Control.DeepSeq (NFData (..))   @@ -83,21 +84,24 @@  data PredTrie k a = PredTrie   { predLits  :: !(HT.HashMapStep PredTrie k a) -- ^ a /literal/ step-  , predPreds :: !(PredSteps k PredTrie k a)      -- ^ a /predicative/ step+  , predPreds :: PredStep k PredTrie k a      -- ^ a /predicative/ step   } deriving (Show, Functor, Typeable) +instance (NFData k, NFData a) => NFData (PredTrie k a) where+  rnf (PredTrie hs ps) = rnf hs `seq` rnf ps+ instance ( Arbitrary k          , Arbitrary a          , Eq k          , Hashable k          ) => Arbitrary (PredTrie k a) where-  arbitrary = flip PredTrie (PredSteps []) <$> arbitrary+  arbitrary = flip PredTrie mempty <$> arbitrary  instance ( Hashable k          , Eq k          ) => Trie NonEmpty k PredTrie where   lookup ts (PredTrie ls ps) =-    getFirst $ (First $! lookup ts ls) <> First (lookup ts ps)+    getFirst (First (lookup ts ls) <> First (lookup ts ps))   delete ts (PredTrie ls ps) = PredTrie (delete ts ls) (delete ts ps)   insert ts x (PredTrie ls ps) = PredTrie (HT.insert ts x ls) ps -- can only insert literals @@ -106,10 +110,10 @@          ) => Monoid (PredTrie k a) where   mempty = PredTrie mempty mempty   mappend (PredTrie ls1 ps1) (PredTrie ls2 ps2) =-    (PredTrie $! ls1 <> ls2) $! ps1 <> ps2+    PredTrie (ls1 <> ls2) (ps1 <> ps2)  emptyPT :: PredTrie k a-emptyPT = PredTrie HT.empty (PredSteps [])+emptyPT = PredTrie HT.empty (PredStep HMS.empty)   -- subtrie :: Ord s => NonEmpty s -> PredTrie s a -> PredTrie s a@@ -121,56 +125,56 @@ matchPT :: ( Hashable k            , Eq k            ) => NonEmpty k -> PredTrie k a -> Maybe (NonEmpty k, a, [k])-matchPT (t:|ts) (PredTrie ls (PredSteps ps)) = getFirst $+matchPT (t:|ts) (PredTrie ls (PredStep ps)) = getFirst $   First (goLit ls) <> foldMap (First . goPred) ps   where     goLit (HT.HashMapStep xs) = do       (HT.HashMapChildren mx mxs) <- HM.lookup t xs-      let mFoundHere = (t:|[],, []) <$> mx+      let mFoundHere = (t:|[],,[]) <$> mx       if null ts       then mFoundHere       else getFirst $ First (do (pre,y,suff) <- matchPT (NE.fromList ts) =<< mxs-                                return (t:|NE.toList pre, y, suff))+                                pure (NE.cons t pre, y, suff))                    <> First mFoundHere -    goPred (PredStep _ p mx xs) = do+    goPred (Pred p mx xs) = do       r <- p t-      let mFoundHere = do x <- mx <$~> r-                          return (t:|[], x, [])+      let mFoundHere = do x <- ($ r) <$> mx+                          pure (t:|[], x, [])       if null ts       then mFoundHere       else getFirst $ First (do (pre,y,suff) <- matchPT (NE.fromList ts) xs-                                return (t:|NE.toList pre, y r, suff))+                                pure (NE.cons t pre, y r, suff))                    <> First mFoundHere   matchesPT :: ( Hashable k              , Eq k              ) => NonEmpty k -> PredTrie k a -> [(NonEmpty k, a, [k])]-matchesPT (t:|ts) (PredTrie ls (PredSteps ps)) =-  fromMaybe [] $ getFirst $ First (goLit ls) <> foldMap (First . goPred) ps+matchesPT (t:|ts) (PredTrie ls (PredStep ps)) =+  fromMaybe [] (getFirst (First (goLit ls) <> foldMap (First . goPred) ps))   where     goLit (HT.HashMapStep xs) = do       (HT.HashMapChildren mx mxs) <- HM.lookup t xs       let mFoundHere = do x <- mx-                          return [(t:|[],x,ts)]-          prependAncestry (pre,x,suff) = (t:| NE.toList pre,x,suff)+                          pure [(t:|[],x,ts)]+          prependAncestry (pre,x,suff) = (NE.cons t pre,x,suff)       if null ts       then mFoundHere       else do foundHere <- mFoundHere-              let rs = fromMaybe [] $! matchesPT (NE.fromList ts) <$> mxs-              return $! foundHere ++ (prependAncestry <$> rs)+              let rs = fromMaybe [] (matchesPT (NE.fromList ts) <$> mxs)+              pure (foundHere ++ (prependAncestry <$> rs)) -    goPred (PredStep _ p mx xs) = do+    goPred (Pred p mx xs) = do       r <- p t-      let mFoundHere = do x <- mx <$~> r-                          return [(t:|[],x,ts)]-          prependAncestryAndApply (pre,x,suff) = (t:| NE.toList pre,x r,suff)+      let mFoundHere = do x <- ($ r) <$> mx+                          pure [(t:|[],x,ts)]+          prependAncestryAndApply (pre,x,suff) = (NE.cons t pre,x r,suff)       if null ts       then mFoundHere       else do foundHere <- mFoundHere               let rs = matchesPT (NE.fromList ts) xs-              return $! foundHere ++ (prependAncestryAndApply <$> rs)+              pure (foundHere ++ (prependAncestryAndApply <$> rs))  -- * Rooted Predicative Trie @@ -187,10 +191,10 @@   lookup ts (RootedPredTrie _ xs) = lookup (NE.fromList ts) xs    delete [] (RootedPredTrie _ xs)  = RootedPredTrie Nothing xs-  delete ts (RootedPredTrie mx xs) = RootedPredTrie mx $! delete (NE.fromList ts) xs+  delete ts (RootedPredTrie mx xs) = RootedPredTrie mx (delete (NE.fromList ts) xs)    insert [] x (RootedPredTrie _ xs)  = RootedPredTrie (Just x) xs-  insert ts x (RootedPredTrie mx xs) = RootedPredTrie mx $! insert (NE.fromList ts) x xs+  insert ts x (RootedPredTrie mx xs) = RootedPredTrie mx (insert (NE.fromList ts) x xs)   instance ( Hashable k@@ -198,7 +202,7 @@          ) => Monoid (RootedPredTrie k a) where   mempty = emptyRPT   mappend (RootedPredTrie mx xs) (RootedPredTrie my ys) = RootedPredTrie-    (getLast $! Last mx <> Last my) $! xs <> ys+    (getLast (Last mx <> Last my)) (xs <> ys)   emptyRPT :: RootedPredTrie k a@@ -219,7 +223,8 @@               ) => [k] -> RootedPredTrie k a -> [([k], a, [k])] matchesRPT [] (RootedPredTrie mx _)  = fromMaybe [] $ (\x -> [([],x,[])]) <$> mx matchesRPT ts (RootedPredTrie mx xs) =-  (foundHere ++) $! fmap allowRoot  (matchesPT (NE.fromList ts) xs)+  foundHere ++ fmap allowRoot  (matchesPT (NE.fromList ts) xs)   where-    foundHere = fromMaybe [] $! (\x -> [([],x,[])]) <$> mx+    foundHere = fromMaybe [] $ do x <- mx+                                  pure [([],x,[])]     allowRoot (pre,x,suff) = (NE.toList pre,x,suff)
src/Data/Trie/Pred/Base/Step.hs view
@@ -5,6 +5,8 @@   , MultiParamTypeClasses   , DeriveFunctor   , DeriveDataTypeable+  , OverloadedLists+  , UndecidableInstances   #-}  {- |@@ -20,82 +22,101 @@ module Data.Trie.Pred.Base.Step where  import Prelude hiding (lookup)-import Data.Trie.Class+import Data.Trie.Class (Trie (..)) import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE -import Data.Typeable-import Data.Functor.Syntax-import Data.Monoid+import Data.Data (Typeable)+import Data.Monoid (First (..), (<>))+import Data.Maybe (maybe)+import Data.Hashable (Hashable)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HMS+import Control.DeepSeq (NFData (..))   -- * Single Predicated Step -data PredStep k c s a = forall r. Typeable r => PredStep-  { -- | Unique identifier for the predicate - used for combination-    predTag  :: !k-  , -- | The predicate, existentially quantified in the successful result @r@+data Pred c s a = forall r. Typeable r => Pred+  { -- | The predicate, existentially quantified in the successful result @r@     predPred :: !(s -> Maybe r)   , -- | The result function, capturing the quantified result @r@ and turning     --   it into a top-level variable @a@.     predData :: !(Maybe (r -> a))   , -- | Any sub-trie must have __all__ results preceeded in arity with     --   the result at this step.-    predSub  :: !(c s (r -> a))+    predSub  :: c s (r -> a)   } deriving (Typeable) -instance ( Show s-         , Show k-         ) => Show (PredStep k c s a) where-  show (PredStep t _ _ _) = "PredStep {predTag=" ++ show t ++ ", ...}"+instance Show (Pred c s a) where+  show (Pred _ mx _) = "Pred { predSub = ##, predData = " ++ maybe "Nothing" (\_ -> "Just ##") mx ++ " }" -instance Functor (c s) => Functor (PredStep k c s) where-  fmap f (PredStep i p mx xs) = (PredStep i p $! f <.$> mx) $! f <.$> xs+instance Functor (c s) => Functor (Pred c s) where+  fmap f (Pred p mx xs) = Pred p ((f .) <$> mx) ((f .) <$> xs) +instance (Functor (c s), NFData (c s (s -> Maybe a))) => NFData (Pred c s a) where+  rnf (Pred p mx xs) =+    ( case mx of+        Nothing -> ()+        Just f -> rnf (\x -> case p x of+                               Nothing -> Nothing+                               Just r -> Just (f r)+                          )+      ) `seq` rnf ((\f -> (\x -> case p x of+                              Nothing -> Nothing+                              Just r -> Just (f r)+                             )+                   ) <$> xs)++ -- | Lookup and delete only - can't arbitrarilly construct a predicated trie.-instance Trie NonEmpty s c => Trie NonEmpty s (PredStep k c) where-  lookup (t:|ts) (PredStep _ p mx xs) = do+instance Trie NonEmpty s c => Trie NonEmpty s (Pred c) where+  lookup (t:|ts) (Pred p mx xs) = do     r <- p t-    if null ts then mx <$~> r-               else lookup (NE.fromList ts) xs <$~> r-  delete (t:|ts) xss@(PredStep i p mx xs) =-    maybe xss-      (const $ if null ts-               then PredStep i p Nothing xs-               else PredStep i p mx $! delete (NE.fromList ts) xs)-      (p t)+    fmap ($ r) $+      if null ts+      then mx+      else lookup (NE.fromList ts) xs+  delete (t:|ts) xss@(Pred p mx xs) =+    case p t of+      Nothing -> xss+      Just _+        | null ts -> Pred p Nothing xs+        | otherwise -> Pred p mx (delete (NE.fromList ts) xs) + singletonPred :: ( Monoid (c s (r -> a))                  , Typeable r-                 ) => k -> (s -> Maybe r) -> (r -> a) -> PredStep k c s a-singletonPred i p x = PredStep i p (Just x) mempty+                 ) => (s -> Maybe r) -> (r -> a) -> Pred c s a+singletonPred p x = Pred p (Just x) mempty   -- * Adjacent Predicated Steps  -- | Adjacent steps-newtype PredSteps k c s a = PredSteps-  { unPredSteps :: [PredStep k c s a]+newtype PredStep k c s a = PredStep+  { unPredSteps :: HashMap k (Pred c s a)   } deriving (Show, Functor, Typeable) ++instance (Functor (c s), NFData (c s (s -> Maybe a)), NFData k) => NFData (PredStep k c s a) where+  rnf (PredStep xs) = rnf xs+ -- | Lookup and delete only - can't arbitrarilly construct a predicated trie.-instance Trie NonEmpty s c => Trie NonEmpty s (PredSteps k c) where-  lookup ts (PredSteps ps) = getFirst $! foldMap (First . lookup ts) ps-  delete ts (PredSteps ps) = PredSteps $! fmap (delete ts) ps+instance Trie NonEmpty s c => Trie NonEmpty s (PredStep k c) where+  lookup ts (PredStep ps) = getFirst (foldMap (First . lookup ts) ps)+  delete ts (PredStep ps) = PredStep (fmap (delete ts) ps) -instance ( Eq s-         , Eq k-         ) => Monoid (PredSteps k c s a) where-  mempty  = PredSteps []+instance ( Eq k+         , Hashable k+         ) => Monoid (PredStep k c s a) where+  mempty  = PredStep HMS.empty   mappend = unionPred --- | @Last@-style instance+-- | overwrite on the right unionPred :: ( Eq k-             ) => PredSteps k c s a-               -> PredSteps k c s a-               -> PredSteps k c s a-unionPred (PredSteps (xss@(PredStep i _ _ _):pxs)) (PredSteps (yss@(PredStep j _ _ _):pys))-  | i == j    = PredSteps $ yss :       (unPredSteps $! unionPred (PredSteps pxs) (PredSteps pys))-  | otherwise = PredSteps $ xss : yss : (unPredSteps $! unionPred (PredSteps pxs) (PredSteps pys))-unionPred x (PredSteps []) = x-unionPred (PredSteps []) y = y+             , Hashable k+             ) => PredStep k c s a+               -> PredStep k c s a+               -> PredStep k c s a+unionPred (PredStep xs) (PredStep ys) = PredStep (xs <> ys)
src/Data/Trie/Pred/Interface/Types.hs view
@@ -11,8 +11,8 @@   , MultiParamTypeClasses   , FunctionalDependencies   , ConstraintKinds-  , BangPatterns   , OverloadedStrings+  , OverloadedLists   #-}  @@ -45,13 +45,13 @@   import Prelude hiding (pred)-import           Data.Trie.Pred.Base-import           Data.Trie.Pred.Base.Step+import           Data.Trie.Pred.Base (RootedPredTrie (..), PredTrie (..), emptyPT)+import           Data.Trie.Pred.Base.Step (Pred (..), PredStep (..)) import qualified Data.Trie.HashMap as HT import qualified Data.HashMap.Lazy as HM-import Data.Hashable-import Data.Function.Poly-import Data.Typeable+import Data.Hashable (Hashable)+import Data.Function.Poly (ArityTypeListIso)+import Data.Typeable (Typeable)  import Data.String (IsString (..)) @@ -95,8 +95,8 @@          , Hashable k          , Typeable r          ) => Extend (PathChunk k ('Just r)) (RootedPredTrie k (r -> a)) (RootedPredTrie k a) where-  extend (Pred i q) (RootedPredTrie mx xs) = RootedPredTrie Nothing $-    PredTrie mempty (PredSteps [PredStep i q mx xs])+  extend (Pred' i q) (RootedPredTrie mx xs) = RootedPredTrie Nothing $+    PredTrie mempty (PredStep (HM.singleton i (Pred q mx xs)))   -- | @FoldR Extend start chunks ~ result@@@ -132,16 +132,16 @@  -- | Match with a predicate against the url chunk directly. pred :: k -> (k -> Maybe r) -> PathChunk k ('Just r)-pred = Pred+pred = Pred'   -- | Constrained to AttoParsec, Regex-Compat and T.Text data PathChunk k (mx :: Maybe *) where-  Lit  :: { litChunk :: !k-          } -> PathChunk k 'Nothing-  Pred :: { predTag  :: !k-          , predPred :: !(k -> Maybe r)-          } -> PathChunk k ('Just r)+  Lit   :: { litChunk :: !k+           } -> PathChunk k 'Nothing+  Pred' :: { predTag  :: !k+           , predPred :: !(k -> Maybe r)+           } -> PathChunk k ('Just r)  -- | Use raw strings instead of prepending @l@ instance IsString k => IsString (PathChunk k 'Nothing) where
− src/Data/Trie/Pred/Mutable.hs
@@ -1,262 +0,0 @@-{-# LANGUAGE-    ExistentialQuantification-  #-}--module Data.Trie.Pred.Mutable where--import Prelude hiding (lookup)-import Data.Monoid-import Data.Maybe (fromMaybe)-import Data.Foldable (foldlM)-import Data.Typeable--import Data.List.NonEmpty hiding (insert)--import           Data.HashTable.ST.Basic (HashTable)-import qualified Data.HashTable.ST.Basic as HT-import           Data.PredSet.Mutable (PredSet, PredKey)-import qualified Data.PredSet.Mutable as HS-import Control.Monad.ST-import Data.Hashable----- * Tail--data PredStep s k r = forall a. Typeable a => PredStep-  { predPred :: {-# UNPACK #-} !(PredKey s k a)-  , predData :: !(Maybe (a -> r))-  , predSub  :: !(HashTableTrie s k (a -> r))-  }--data RawValue s k a = RawValue-  { rawValue    :: !(Maybe a)-  , rawChildren :: !(HashTableTrie s k a)-  }--data HashTableTrie s k a = HashTableTrie-  { rawValues :: {-# UNPACK #-} !(HashTable s k (RawValue s k a))-  , predPreds :: [PredStep s k a]-  }---new :: ST s (HashTableTrie s k a)-new = flip HashTableTrie [] <$> HT.new--insert :: ( Eq k-          , Hashable k-          ) => NonEmpty k-            -> a-            -> HashTableTrie s k a-            -> ST s (HashTableTrie s k a)-insert (k:|ks) x ref@(HashTableTrie raw _) =-  case ks of-    [] -> do-      mx' <- HT.lookup raw k-      case mx' of-        Nothing -> do-          children <- new-          HT.insert raw k $! RawValue (Just x) children-          pure ref-        Just (RawValue _ children) -> do-          HT.insert raw k $! RawValue (Just x) children-          pure ref-    (k':ks') -> do-      mx' <- HT.lookup raw k-      case mx' of-        Nothing -> do-          children <- new-          children' <- insert (k':|ks') x children-          HT.insert raw k $! RawValue Nothing children'-          pure ref-        Just (RawValue mx children) -> do-          children' <- insert (k':|ks') x children-          HT.insert raw k $! RawValue mx children'-          pure ref---lookup :: ( Eq k-          , Hashable k-          , Typeable s-          , Typeable k-          ) => PredSet s k-            -> NonEmpty k-            -> HashTableTrie s k a-            -> ST s (Maybe a)-lookup predSet (k:|ks) (HashTableTrie raw preds) = do-  mx <- HT.lookup raw k-  case mx of-    Just (RawValue mx' children) ->-      case ks of-        []       -> pure mx'-        (k':ks') -> lookup predSet (k':|ks') children-    Nothing ->-      let -- go :: Typeable t => Maybe t -> PredStep s k t -> ST s (Maybe t)-          go solution@(Just _) _                          = pure solution-          go Nothing (PredStep predKey mHandler children) = do-            mx' <- HS.lookup predKey k predSet-            case mx' of-              Nothing -> pure Nothing-              Just x  ->-                case ks of-                  [] ->-                    pure $! ($ x) <$> mHandler-                  (k':ks') -> do-                    mf <- lookup predSet (k':|ks') children-                    pure $! ($ x) <$> mf-      in  foldlM go Nothing preds---match :: ( Eq k-         , Hashable k-         , Typeable s-         , Typeable k-         ) => PredSet s k-           -> NonEmpty k-           -> HashTableTrie s k a-           -> ST s (Maybe (NonEmpty k, a, [k]))-match predSet (k:|ks) (HashTableTrie raw preds) = do-  mLit <- goLit raw-  case mLit of-    Just _  -> pure mLit-    Nothing ->-      let go solution@(Just _) _ = pure solution-          go Nothing pred        = goPred pred-      in  foldlM go Nothing preds-  where-    goLit xs = do-      mx' <- HT.lookup raw k-      case mx' of-        Nothing -> pure Nothing-        Just (RawValue mx children) ->-          let mFoundHere = (\x -> (k:|[], x, ks)) <$> mx-              prependAncestry (pre,x,suff) = (k:|toList pre,x,suff)-          in case ks of-            [] -> pure mFoundHere-            (k':ks') -> do-              mFoundThere <- match predSet (k':|ks') children-              pure $! getFirst $-                   First (prependAncestry <$> mFoundThere)-                <> First mFoundHere--    goPred (PredStep predKey mx children) = do-      mr' <- HS.lookup predKey k predSet-      case mr' of-        Nothing -> pure Nothing-        Just r  ->-          let mFoundHere = (\x -> (k:|[], x r, ks)) <$> mx-              prependAncestryAndApply (pre,f,suff) =-                (k:|toList pre,f r,suff)-          in case ks of-            [] -> pure mFoundHere-            (k':ks') -> do-              mFoundThere <- match predSet (k':|ks') children-              pure $! getFirst $-                   First (prependAncestryAndApply <$> mFoundThere)-                <> First mFoundHere--matches :: ( Eq k-           , Hashable k-           , Typeable s-           , Typeable k-           ) => PredSet s k-             -> NonEmpty k-             -> HashTableTrie s k a-             -> ST s [(NonEmpty k, a, [k])]-matches predSet (k:|ks) (HashTableTrie raw preds) = do-  mLit <- goLit raw-  case mLit of-    Just lit -> pure lit-    Nothing ->-      let go solution@(Just _) _ = pure solution-          go Nothing pred        = goPred pred-      in  fromMaybe [] <$> foldlM go Nothing preds-  where-    goLit xs = do-      mx' <- HT.lookup raw k-      case mx' of-        Nothing -> pure Nothing-        Just (RawValue mx children) ->-          let mFoundHere = (\x -> [(k:|[], x, ks)]) <$> mx-              prependAncestry (pre,x,suff) = (k:|toList pre, x, suff)-          in case ks of-            [] -> pure mFoundHere-            (k':ks') ->-              case mFoundHere of-                Nothing -> pure Nothing-                Just foundHere -> do-                  foundThere <- matches predSet (k':|ks') children-                  pure . Just $! foundHere ++ (prependAncestry <$> foundThere)--    goPred (PredStep predKey mx children) = do-      mr <- HS.lookup predKey k predSet-      case mr of-        Nothing -> pure Nothing-        Just r  ->-          let mFoundHere = (\f -> [(k:|[],f r,ks)]) <$> mx-              prependAncestryAndApply (pre,f,suff) =-                (k:|toList pre,f r,suff)-          in case ks of-            [] -> pure mFoundHere-            (k':ks') ->-              case mFoundHere of-                Nothing -> pure Nothing-                Just foundHere -> do-                  foundThere <- matches predSet (k':|ks') children-                  pure . Just $! foundHere ++ (prependAncestryAndApply <$> foundThere)----- * Rooted--data RootedHashTableTrie s k a = RootedHashTableTrie-  { rootedBase    :: !(Maybe a)-  , rootedSub     :: !(HashTableTrie s k a)-  , rootedPredSet :: {-# UNPACK #-} !(PredSet s k)-  }--newR :: ST s (RootedHashTableTrie s k a)-newR = RootedHashTableTrie Nothing <$> new <*> HS.new--lookupR :: ( Eq k-           , Hashable k-           , Typeable s-           , Typeable k-           , Typeable a-           ) => [k]-             -> RootedHashTableTrie s k a-             -> ST s (Maybe a)-lookupR [] (RootedHashTableTrie mx _ _) = pure mx-lookupR (k:ks) (RootedHashTableTrie _ xs predSet) = lookup predSet (k:|ks) xs--matchR :: ( Eq k-          , Hashable k-          , Typeable s-          , Typeable k-          , Typeable a-          ) => [k]-            -> RootedHashTableTrie s k a-            -> ST s (Maybe ([k],a,[k]))-matchR [] (RootedHashTableTrie mx _ _) =-  pure $! (\x -> ([],x,[])) <$> mx-matchR (k:ks) (RootedHashTableTrie mx xs predSet) = do-  mFoundThere <- match predSet (k:|ks) xs-  pure $! getFirst $-      First ((\(pre,x,suff) -> (toList pre,x,suff)) <$> mFoundThere)-   <> First ((\x -> ([],x,k:ks)) <$> mx)---matchesR :: ( Eq k-            , Hashable k-            , Typeable s-            , Typeable k-            , Typeable a-            ) => [k]-              -> RootedHashTableTrie s k a-              -> ST s [([k],a,[k])]-matchesR [] (RootedHashTableTrie mx _ _) =-  pure $! fromMaybe [] $ (\x -> [([],x,[])]) <$> mx-matchesR (k:ks) (RootedHashTableTrie mx xs predSet) = do-  foundThere <- matches predSet (k:|ks) xs-  pure $! foundHere ++ (allowRoot <$> foundThere)-  where-    foundHere = fromMaybe [] $ (\x -> [([],x,k:ks)]) <$> mx-    allowRoot (pre,x,suff) = (toList pre,x,suff)
− src/Data/Trie/Pred/Mutable/Morph.hs
@@ -1,137 +0,0 @@-module Data.Trie.Pred.Mutable.Morph where--import Data.Trie.Pred.Mutable as M-import Data.Trie.Pred.Base as B-import Data.Trie.Pred.Base.Step as B--import Data.PredSet.Mutable as HS-import Data.Trie.HashMap as HMT-import           Data.HashMap.Lazy (HashMap)-import qualified Data.HashMap.Lazy as HM-import           Data.HashTable.ST.Basic (HashTable)-import qualified Data.HashTable.ST.Basic as HT-import qualified Data.Map.Strict as Map--import Control.Monad.ST-import Data.Foldable (foldlM)-import Data.Typeable-import Data.Dynamic-import Data.Hashable-import Data.Proxy-import Data.STRef---toMutableRooted :: ( Eq k-                   , Hashable k-                   , Ord k-                   , Typeable s-                   , Typeable k-                   , Typeable a-                   ) => RootedPredTrie k a-                     -> ST s (RootedHashTableTrie s k a)-toMutableRooted (RootedPredTrie mx xs) = do-  predSet <- HS.new-  xs' <- toMutable predSet xs-  pure $! RootedHashTableTrie mx xs' predSet--toMutable :: ( Eq k-             , Hashable k-             , Ord k-             , Typeable s-             , Typeable k-             , Typeable a-             ) => PredSet s k-               -> PredTrie k a-               -> ST s (HashTableTrie s k a)-toMutable predSet xs = do-  predRefs <- newSTRef Map.empty-  toHashTableTrie predRefs predSet xs---toHashTableTrie :: ( Eq k-                   , Hashable k-                   , Ord k-                   , Typeable s-                   , Typeable k-                   , Typeable a-                   ) => STRef s (HMap k)-                     -> PredSet s k-                     -> PredTrie k a-                     -> ST s (HashTableTrie s k a)-toHashTableTrie predRefs predSet (PredTrie (HashMapStep raw) (PredSteps preds)) = do-  raw' <- toHashTable =<< traverse (toRawValue predRefs predSet) raw-  preds' <- mapM (toMutablePredStep predRefs predSet) preds-  pure (HashTableTrie raw' preds')--toRawValue :: ( Eq k-              , Hashable k-              , Ord k-              , Typeable s-              , Typeable k-              , Typeable a-              ) => STRef s (HMap k)-                -> PredSet s k-                -> HashMapChildren PredTrie k a-                -> ST s (RawValue s k a)-toRawValue predRefs predSet (HashMapChildren mx mchildren) = do-  children <- case mchildren of-                Nothing -> M.new-                Just xs -> toHashTableTrie predRefs predSet xs-  pure (RawValue mx children)--toHashTable :: ( Eq k-               , Hashable k-               ) => HM.HashMap k a-                 -> ST s (HashTable s k a)-toHashTable xs = do-  fresh <- HT.new-  foldlM (\() (k,v) -> HT.insert fresh k v) () (HM.toList xs)-  pure fresh--toMutablePredStep :: ( Ord k-                     , Eq k-                     , Hashable k-                     , Typeable s-                     , Typeable k-                     , Typeable a-                     ) => STRef s (HMap k)-                       -> PredSet s k-                       -> B.PredStep k PredTrie k a-                       -> ST s (M.PredStep s k a)-toMutablePredStep predRefs predSet (B.PredStep tag pred mx children) = do-  predRefs' <- readSTRef predRefs-  mPredKey <- lookupPredKey tag (pure pred) predRefs'-  predKey  <- case mPredKey of-                Nothing -> do predKey' <- HS.insert pred predSet-                              writeSTRef predRefs (insertPredKey tag predKey' predRefs')-                              pure predKey'-                Just x  -> pure x-  children' <- toHashTableTrie predRefs predSet children-  pure (M.PredStep predKey mx children')----- Wiiiked abuse of the type system--type HMap k = Map.Map k Dynamic--insertPredKey :: ( Ord k'-                 , Typeable s-                 , Typeable k-                 , Typeable a-                 ) => k'-                   -> PredKey s k a-                   -> HMap k'-                   -> HMap k'-insertPredKey k pred = Map.insert k (toDyn pred)--lookupPredKey :: ( Ord k'-                 , Typeable s-                 , Typeable k-                 , Typeable a-                 ) => k'-                   -> ST s (k -> Maybe a)-                   -> HMap k'-                   -> ST s (Maybe (PredKey s k a))-lookupPredKey k pred xs = do-  pred' <- pred-  pure $! fromDynamic =<< Map.lookup k xs
test/Data/Trie/PredSpec.hs view
@@ -4,20 +4,19 @@  module Data.Trie.PredSpec where -import Data.Trie.Pred.Base-import Data.Trie.Pred.Base.Step-import Data.Trie.Class+import Data.Trie.Pred.Base (PredTrie (..), emptyPT)+import Data.Trie.Pred.Base.Step (PredStep (..), Pred (..))+import Data.Trie.Class (Trie (lookup, insert, delete)) import Data.Trie.HashMap (HashMapStep (..)) import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE -import qualified Data.HashMap.Lazy as HM+import qualified Data.HashMap.Strict as HM import Data.Attoparsec.Text (parseOnly, double) import qualified Data.Text as T import Control.Error (hush) import Prelude hiding (lookup)-import Test.QuickCheck-import Test.Tasty+import Test.Tasty (TestTree, testGroup) import Test.Tasty.QuickCheck as QC  @@ -46,4 +45,4 @@  doubleTable :: PredTrie T.Text Int doubleTable = PredTrie (HashMapStep HM.empty) $-  PredSteps [PredStep "double" (hush . parseOnly double) (Just $ \d -> 0) emptyPT]+  PredStep (HM.singleton "double" (Pred (hush . parseOnly double) (Just $ \d -> 0) emptyPT))