pred-trie-0.5.1: src/Data/Trie/Pred/Interface.hs
{-# 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