-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Pattern tries -- -- Simple pattern tries for structured keys, where lookups can capture -- (parts of) the input strings. @package pattern-trie @version 0.1.0 -- | A variant of a (radix) trie with the following characteristics: -- --
-- >>> :set -XOverloadedStrings ---- --
-- >>> import Data.ByteString (ByteString) ---- --
-- >>> let p1 = mempty |> EqStr "home" |> EqStr "alice" |> EqStr "tmp" -- -- >>> let p2 = mempty |> EqStr "home" |> AnyStr |> EqStr "music" -- -- >>> let p3 = mempty |> EqStr "data" |> EqStr "bob" |> EqStr "books" -- -- >>> let p4 = mempty |> EqStr "data" |> AnyStr |> EqStr "books" -- -- >>> let p5 = mempty |> EqStr "data" |> AnyStr |> EqStr "books" |> EqStr "sicp" ---- --
-- >>> let trie = fromAssocList $ [p1,p2,p3,p4,p5] `zip` [1..] :: Trie ByteString Int ---- --
-- >>> match ["home","alice","tmp"] trie -- Just (1,fromList []) ---- --
-- >>> match ["home","bob","tmp"] trie -- Nothing ---- --
-- >>> match ["home","alice","music"] trie
-- Just (2,fromList [Capture {captured = "alice"}])
--
--
--
-- >>> match ["home","bob","music"] trie
-- Just (2,fromList [Capture {captured = "bob"}])
--
--
-- -- >>> match ["data","bob","books"] trie -- Just (3,fromList []) ---- --
-- >>> match ["data","alice","books"] trie
-- Just (4,fromList [Capture {captured = "alice"}])
--
--
--
-- >>> match ["data","alice","books","sicp"] trie
-- Just (5,fromList [Capture {captured = "alice"}])
--
--
--
-- >>> match ["data","bob","books","sicp"] trie
-- Just (5,fromList [Capture {captured = "bob"}])
--
--
--
-- >>> matchPrefix ["data","alice","books","wonderland"] trie
-- Just (4,fromList [Capture {captured = "alice"}],["wonderland"])
--
--
--
-- >>> matchPrefix ["data","bob","books","wonderland"] trie
-- Just (4,fromList [Capture {captured = "bob"}],["wonderland"])
--
--
--
-- >>> let (t,c,s) = matchPrefixTrie ["data","bob","books","wonderland"] trie
--
-- >>> (value t, c, s)
-- (Just 4,fromList [Capture {captured = "bob"}],["wonderland"])
--
module Data.Trie.Pattern
-- | An unordered map from Patterns of strings of type s to
-- values of type a.
data Trie s a
-- | The value at the root of the trie, i.e.
--
-- -- value t == lookup mempty t --value :: Trie s a -> (Maybe a) -- | A pattern is a sequence of Matchers and serves as a key in a -- pattern trie. -- -- If two patterns are overlapping for an input string, the preference -- for a match is given by the partial order EqStr > -- AnyStr on the competing matchers, i.e. towards the more specific -- pattern. This partial order is witnessed and subsumed by the total -- order MatchOrd. -- -- The preference for a prefix match is reversed, i.e. for an input -- string where only a proper prefix is a match for overlapping patterns, -- the preference is given by the partial order AnyStr > -- EqStr, i.e. towards the more general pattern. This partial order -- is witnessed and subsumed by the total order PrefixMatchOrd. type Pattern s = Seq (Matcher s) -- | A (chunked) input string to match on a Pattern in a -- trie. -- -- Note: Input strings can be infinite. Since the tries are always -- finite, an infinite input string is only consumed until either a match -- has been found or the applicable paths in the trie have been -- exhaustively searched. type Str s = [s] -- | A Matcher is applied on a single chunk of an input -- String while looking for a match and either -- succeeds or fails. If it succeeds, it may Capture -- the chunk. data Matcher s -- | Match and capture an arbitrary chunk of an input string. AnyStr :: Matcher s -- | Match a chunk of an input string exactly, capturing nothing. EqStr :: !s -> Matcher s -- | A captured chunk of an input String. newtype Capture s Capture :: s -> Capture s [captured] :: Capture s -> s -- | Check whether two patterns are overlapping, i.e. whether there exists -- a String that is a (full) match for both patterns. -- --
-- >>> let p1 = mempty |> EqStr "a" |> AnyStr -- -- >>> let p2 = mempty |> AnyStr |> EqStr "b" -- -- >>> let p3 = mempty |> EqStr "a" |> EqStr "c" -- -- >>> overlapping p1 p1 -- False -- -- >>> overlapping p1 p2 -- True -- -- >>> overlapping p1 p3 -- True -- -- >>> overlapping p2 p3 -- False --overlapping :: Eq s => Pattern s -> Pattern s -> Bool -- | A total order for matchers that subsumes the partial order for the -- preference between overlapping patterns on a match. -- --
-- >>> MatchOrd AnyStr < MatchOrd (EqStr "a") -- True ---- --
-- >>> let p1 = mempty |> EqStr "a" |> EqStr "b" -- -- >>> let p2 = mempty |> AnyStr |> EqStr "b" -- -- >>> matchOrd p1 > matchOrd p2 -- True --newtype MatchOrd s MatchOrd :: (Matcher s) -> MatchOrd s -- | A total order for matchers that subsumes the partial order for the -- preference between overlapping patterns on a matchPrefix. -- --
-- >>> MatchPrefixOrd AnyStr > MatchPrefixOrd (EqStr "a") -- True ---- --
-- >>> let p1 = mempty |> EqStr "a" |> EqStr "b" -- -- >>> let p2 = mempty |> AnyStr |> EqStr "b" -- -- >>> matchPrefixOrd p1 < matchPrefixOrd p2 -- True --newtype MatchPrefixOrd s MatchPrefixOrd :: (Matcher s) -> MatchPrefixOrd s matchOrd :: Pattern s -> Seq (MatchOrd s) matchPrefixOrd :: Pattern s -> Seq (MatchPrefixOrd s) -- | Apply a string to a pattern, returning the unmatched suffix of the -- pattern together with the captured chunks and the remaining -- (unmatched) suffix of the input string. -- --
-- >>> let p = mempty |> EqStr "a" |> AnyStr |> EqStr "c"
--
-- >>> let s = ["a", "b", "d"]
--
-- >>> apply s p
-- (fromList [EqStr "c"],fromList [Capture {captured = "b"}],["d"])
--
apply :: Eq s => Str s -> Pattern s -> (Pattern s, Seq (Capture s), Str s)
-- | Apply a string to a pattern, returning the captures.
--
--
-- >>> let p = mempty |> EqStr "a" |> AnyStr |> EqStr "c"
--
-- >>> let s = ["a", "b", "d"]
--
-- >>> applyCapture s p
-- fromList [Capture {captured = "b"}]
--
applyCapture :: Eq s => Str s -> Pattern s -> Seq (Capture s)
-- | (Re)Construct the longest input String matching a prefix of a
-- pattern, using the given captures to satisfy matchers. As long as
-- there are enough captures to satisfy all matchers in the pattern, the
-- resulting string will always be a (full) match for the pattern.
--
-- Furthermore, if an input string s is a (full) match for a
-- pattern p, then
--
-- -- unapplyCapture p (applyCapture s p) == s ---- --
-- >>> let p = mempty |> EqStr "a" |> AnyStr |> EqStr "c" -- -- >>> let s = ["a", "b", "c"] -- -- >>> unapplyCapture p (applyCapture s p) -- ["a","b","c"] --unapplyCapture :: Pattern s -> Seq (Capture s) -> Str s -- | Apply a string to a pattern, returning the captures iff the string is -- a (full) match for the pattern. -- --
-- >>> let p = mempty |> EqStr "a" |> AnyStr |> EqStr "c"
--
-- >>> applyMatch ["a", "b", "c", "d"] p
-- Nothing
--
-- >>> applyMatch ["a", "b", "c"] p
-- Just (fromList [Capture {captured = "b"}])
--
applyMatch :: Eq s => Str s -> Pattern s -> Maybe (Seq (Capture s))
-- | Apply a string to a pattern, returning True iff the string is a
-- (full) match for the pattern.
applyMatches :: Eq s => Str s -> Pattern s -> Bool
-- | Apply a string to a pattern, returning the captures iff the string is
-- a prefix match for the pattern.
--
--
-- >>> let p = mempty |> EqStr "a" |> AnyStr |> EqStr "c"
--
-- >>> applyMatchPrefix ["a", "b", "c", "d"] p
-- Just (fromList [Capture {captured = "b"}])
--
applyMatchPrefix :: Eq s => Str s -> Pattern s -> Maybe (Seq (Capture s))
-- | Apply a string to a pattern, returning True iff the string is a
-- prefix match for the pattern.
applyMatchesPrefix :: Eq s => Str s -> Pattern s -> Bool
-- | Create a pattern trie from a list of patterns and associated values.
--
-- <math>, where <math> is the length of the list and
-- <math> is the length of the longest pattern in the list.
fromAssocList :: (Eq s, Hashable s) => [(Pattern s, a)] -> Trie s a
-- | Create a list of patterns and associated values from a pattern trie.
--
-- <math>, where <math> is the number of values in the trie
-- and <math> is the length of the longest pattern in the trie.
toAssocList :: (Eq s, Hashable s) => Trie s a -> [(Pattern s, a)]
-- | Insert the value for the given pattern into the trie.
--
-- <math>, where <math> is the length of the pattern.
insert :: (Eq s, Hashable s) => Pattern s -> a -> Trie s a -> Trie s a
-- | Update the value of the given pattern in the trie, if it exists.
--
-- <math>, where <math> is the length of the pattern.
adjust :: (Eq s, Hashable s) => Pattern s -> (a -> a) -> Trie s a -> Trie s a
-- | Remove the value for the given pattern from the trie, if it exists.
--
-- <math>, where <math> is the length of the pattern.
delete :: (Eq s, Hashable s) => Pattern s -> Trie s a -> Trie s a
-- | Lookup the value of a pattern. If there is no value in the trie for
-- the given pattern, the result is Nothing.
lookup :: (Eq s, Hashable s) => Pattern s -> Trie s a -> Maybe a
-- | Lookup the value for the longest matching prefix of a pattern,
-- returning it together with the remaining suffix of the pattern. If
-- there is no value in the trie for any prefix of the given pattern, the
-- result is Nothing.
lookupPrefix :: (Eq s, Hashable s) => Pattern s -> Trie s a -> Maybe (a, Pattern s)
-- | Lookup the trie rooted at the longest prefix of a pattern, returning
-- it together with the remaining suffix of the pattern.
lookupPrefixTrie :: (Eq s, Hashable s) => Pattern s -> Trie s a -> (Trie s a, Pattern s)
-- | Lookup the value for an input string by matching it against the
-- patterns of a trie. The value of the matching pattern, if any, is
-- returned together with any captured parts of the input string. If the
-- input string does not match any pattern in the trie, the result is
-- Nothing.
match :: (Eq s, Hashable s) => Str s -> Trie s a -> Maybe (a, Seq (Capture s))
-- | Lookup the value for the longest matching prefix of the input string,
-- returning it together with any captured parts and the remaining
-- (unmatched) suffix of the input string. If no prefix of the input
-- string matches any pattern in the trie, the result is Nothing.
matchPrefix :: (Eq s, Hashable s) => Str s -> Trie s a -> Maybe (a, Seq (Capture s), Str s)
-- | Lookup the trie rooted at the longest matching prefix of the input
-- string, returning it together with any captured parts and the
-- remaining (unmatched) suffix of the input string.
--
-- In particular, if the input string is a (full) match for a pattern,
-- the returned trie is the subtrie that is rooted at the associated
-- value.
matchPrefixTrie :: (Eq s, Hashable s) => Str s -> Trie s a -> (Trie s a, Seq (Capture s), Str s)
traverseWithKey :: Applicative f => (Pattern s -> a -> f b) -> Trie s a -> f (Trie s b)
foldMapWithKey :: Monoid m => (Pattern s -> a -> m) -> Trie s a -> m
foldrWithKey :: (Pattern s -> a -> b -> b) -> b -> Trie s a -> b
-- | <math>. Add an element to the right end of a sequence. Mnemonic:
-- a triangle with the single element at the pointy end.
(|>) :: () => Seq a -> a -> Seq a
infixl 5 |>
instance GHC.Classes.Eq s => GHC.Classes.Eq (Data.Trie.Pattern.MatchOrd s)
instance GHC.Classes.Eq s => GHC.Classes.Eq (Data.Trie.Pattern.MatchPrefixOrd s)
instance Control.DeepSeq.NFData s => Control.DeepSeq.NFData (Data.Trie.Pattern.Matcher s)
instance GHC.Generics.Generic (Data.Trie.Pattern.Matcher s)
instance GHC.Read.Read s => GHC.Read.Read (Data.Trie.Pattern.Matcher s)
instance GHC.Show.Show s => GHC.Show.Show (Data.Trie.Pattern.Matcher s)
instance GHC.Classes.Eq s => GHC.Classes.Eq (Data.Trie.Pattern.Matcher s)
instance Control.DeepSeq.NFData s => Control.DeepSeq.NFData (Data.Trie.Pattern.Capture s)
instance GHC.Generics.Generic (Data.Trie.Pattern.Capture s)
instance GHC.Read.Read s => GHC.Read.Read (Data.Trie.Pattern.Capture s)
instance GHC.Show.Show s => GHC.Show.Show (Data.Trie.Pattern.Capture s)
instance GHC.Classes.Ord s => GHC.Classes.Ord (Data.Trie.Pattern.Capture s)
instance GHC.Classes.Eq s => GHC.Classes.Eq (Data.Trie.Pattern.Capture s)
instance (Control.DeepSeq.NFData s, Control.DeepSeq.NFData a) => Control.DeepSeq.NFData (Data.Trie.Pattern.Trie s a)
instance GHC.Generics.Generic (Data.Trie.Pattern.Trie s a)
instance (GHC.Classes.Eq s, Data.Hashable.Class.Hashable s, GHC.Read.Read s, GHC.Read.Read a) => GHC.Read.Read (Data.Trie.Pattern.Trie s a)
instance (GHC.Show.Show s, GHC.Show.Show a) => GHC.Show.Show (Data.Trie.Pattern.Trie s a)
instance (GHC.Classes.Eq s, GHC.Classes.Eq a) => GHC.Classes.Eq (Data.Trie.Pattern.Trie s a)
instance GHC.Classes.Ord s => GHC.Classes.Ord (Data.Trie.Pattern.MatchOrd s)
instance GHC.Classes.Ord s => GHC.Classes.Ord (Data.Trie.Pattern.MatchPrefixOrd s)
instance Data.Traversable.Traversable (Data.Trie.Pattern.Trie s)
instance GHC.Base.Functor (Data.Trie.Pattern.Trie s)
instance Data.Foldable.Foldable (Data.Trie.Pattern.Trie s)
instance (GHC.Classes.Eq s, Data.Hashable.Class.Hashable s) => GHC.Base.Semigroup (Data.Trie.Pattern.Trie s a)
instance (GHC.Classes.Eq s, Data.Hashable.Class.Hashable s) => GHC.Base.Monoid (Data.Trie.Pattern.Trie s a)