{-# LANGUAGE GeneralizedNewtypeDeriving , MultiParamTypeClasses , DeriveFunctor , BangPatterns , FlexibleContexts , TypeFamilies #-} {- | Module : Data.Trie.Pred.Interface Copyright : (c) 2015 Athan Clark License : BSD-style Maintainer : athan.clark@gmail.com Stability : experimental Portability : GHC This module defines a "builder" monad, which aides in the process of building a trie. It's a monad transformer, so you can use it alongside whichever context you're already working in. > myBuilder :: ( Eq k > , Hashable k > , MonadIO m > ) => PTBuilder String Int m () > myBuilder = do > insertHere 0 > insert ("some" ./ "path" ./ nil) 1 > insert ("some" ./ pred "pred-chunk" upperPred ./ nil) 2 > prefix ("some") $ do > insert ("thing" ./ nil) 3 > insert ("else" ./ nil) 4 > data <- liftIO (doSomething) > insert ("another" ./ "thing" ./ nil) data > where > uppderPred :: String -> Maybe String > uppderPred s | all isUpperCase s = Just s > | otherwise = Nothing > Then we can get our trie to perform lookups by executing the monad: > main :: IO () > main = do > trie <- execPTBuilderT myBuilder > print (lookup ["foo", "bar", "baz"] trie) -} module Data.Trie.Pred.Interface ( -- * Construction -- ** Builder Monad PTBuilderT (..) , execPTBuilderT , -- ** Combinators insert , insertHere , prefix , -- ** Specifying Paths only , pred , (./) , nil , -- * Query lookup , match , matches , -- * Delete delete , -- * Types RootedPredTrie , PathChunks , PathChunk ) where import Prelude hiding (lookup, pred) import Data.Trie.Pred.Base import Data.Trie.Pred.Interface.Types import Data.Function.Poly import qualified Data.Trie.Class as TC import Data.Hashable import Data.Monoid import Control.Monad.State import Control.Monad.Writer -- * Building Tries newtype PTBuilderT k v m a = PTBuilderT { runPTBuilderT :: StateT (RootedPredTrie k v) m a } deriving ( Functor, Applicative, Monad, MonadTrans , MonadState (RootedPredTrie k v)) instance ( Monad m , Eq k , Hashable k ) => MonadWriter (RootedPredTrie k v) (PTBuilderT k v m) where tell x = modify' (x <>) listen x = do x' <- x w <- get return (x', w) pass x = do (x', f) <- x modify' f return x' execPTBuilderT :: ( Monad m , Eq k , Hashable k ) => PTBuilderT k v m a -> m (RootedPredTrie k v) execPTBuilderT = flip execStateT mempty . runPTBuilderT -- * Combinators insert :: ( Monad m , Eq k , Hashable k , Singleton (PathChunks k xs) childContent (RootedPredTrie k resultContent) , cleanxs ~ CatMaybes xs , ArityTypeListIso childContent cleanxs resultContent ) => PathChunks k xs -> childContent -> PTBuilderT k resultContent m () insert !ts !vl = modify' (singleton ts vl <>) insertHere :: ( Monad m , Eq k , Hashable k ) => v -> PTBuilderT k v m () insertHere = insert nil prefix :: ( Monad m , Eq k , Hashable k , cleanxs ~ CatMaybes xs , ExtrudeSoundly k cleanxs xs childContent resultContent ) => PathChunks k xs -> PTBuilderT k childContent m () -> PTBuilderT k resultContent m () prefix !ts cs = do trie <- lift (execPTBuilderT cs) modify' (extrude ts trie <>) lookup :: ( Eq k , Hashable k ) => [k] -> RootedPredTrie k a -> Maybe a lookup = TC.lookup delete :: ( Eq k , Hashable k ) => [k] -> RootedPredTrie k a -> RootedPredTrie k a delete = TC.delete match :: ( Hashable k , Eq k ) => [k] -> RootedPredTrie k a -> Maybe ([k], a, [k]) match = matchRPT matches :: ( Hashable k , Eq k ) => [k] -> RootedPredTrie k a -> [([k], a, [k])] matches = matchesRPT