pred-trie-0.4.0: src/Data/Trie/Pred/Step.hs
{-# LANGUAGE
ExistentialQuantification
, FlexibleContexts
, FlexibleInstances
, MultiParamTypeClasses
, DeriveFunctor
, DeriveGeneric
, DeriveDataTypeable
, BangPatterns
#-}
{- |
Module : Data.Trie.Pred
Copyright : (c) 2015 Athan Clark
License : BSD-3
Maintainer : athan.clark@gmail.com
Stability : experimental
Portability : GHC
-}
module Data.Trie.Pred.Step where
import Prelude hiding (lookup)
import Data.Trie.Class
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Typeable
import Data.Functor.Syntax
import Data.Monoid
-- * 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 -- ^ The predicate, existentially quantified in the successful result @r@
, predData :: Maybe (r -> a) -- ^ The result function, capturing the quantified result @r@ and turning
-- it into a top-level variable @a@.
, predSub :: c s (r -> a) -- ^ Any sub-trie must have __all__ results preceeded in arity with
-- the result at this step.
} deriving (Typeable)
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
-- | Adjacent steps
newtype PredSteps c s a = PredSteps
{ unPredSteps :: [PredStep c s a]
} deriving (Functor, Typeable)
-- | 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 _ _ _):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