pred-trie-0.3.0: src/Data/Trie/Pred/Step.hs
{-# LANGUAGE
ExistentialQuantification
, FlexibleContexts
, FlexibleInstances
, MultiParamTypeClasses
, DeriveFunctor
#-}
module Data.Trie.Pred.Step where
import Prelude hiding (lookup)
import Data.Trie.Class
import qualified Data.Trie.Map as MT
import qualified Data.Map as Map
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Functor.Syntax
import Data.Monoid
import Data.Maybe (fromMaybe)
-- * Single Predicated Step
data PredStep c s a = forall r. PredStep
{ predTag :: s -- ^ Unique identifier for the predicate - used for combination
, predPred :: s -> Maybe r
, predData :: Maybe (r -> a)
, predSub :: c s (r -> a)
}
instance Functor (c s) => Functor (PredStep c s) where
fmap f (PredStep i p mx xs) = PredStep i p (f <.$> mx) $ f <.$> xs
-- | Lookup and delete only - can't arbitrarilly construct a predicated trie.
instance Trie NonEmpty s c => Trie NonEmpty s (PredStep c) where
lookup (t:|ts) (PredStep _ 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)
singletonPred :: Monoid (c s (r -> a)) => s -> (s -> Maybe r) -> (r -> a) -> PredStep c s a
singletonPred i p x = PredStep i p (Just x) mempty
-- * Adjacent Predicated Steps
newtype PredSteps c s a = PredSteps
{ unPredSteps :: [PredStep c s a] }
deriving (Functor)
-- | Lookup and delete only - can't arbitrarilly construct a predicated trie.
instance Trie NonEmpty s c => Trie NonEmpty s (PredSteps c) where
lookup ts (PredSteps ps) = getFirst $ foldMap (First . lookup ts) ps
delete ts (PredSteps ps) = PredSteps $ fmap (delete ts) ps
instance Eq s => Monoid (PredSteps c s a) where
mempty = PredSteps []
mappend = unionPred
-- | @Last@-style instance
unionPred :: Eq s => PredSteps c s a -> PredSteps c s a -> PredSteps c s a
unionPred (PredSteps (xss@(PredStep i p mx xs):pxs)) (PredSteps (yss@(PredStep j q my ys):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