-- | A generic extracting predicate. module Text.XML.PolySoup.Predicate ( Q (..) , true , satisfy ) where import Control.Applicative -- | A predicate checks if the given element satisfies some properties -- and extracts its attribute values. You can compose predicates using -- Functor, Applicative and Alternative operators: '*>', '<*', '<|>' etc. -- Note, that it doesn't really have sense to use function like `many` -- or `some`, since the extracting predicate doesn't consume any input. newtype Q a b = Q { runQ :: (a -> Maybe b) } instance Functor (Q a) where fmap f (Q g) = Q $ fmap (fmap f) g instance Applicative (Q a) where pure = Q . const . Just Q f <*> Q p = Q $ \x -> f x <*> p x instance Alternative (Q a) where empty = Q $ \_ -> Nothing Q p <|> Q p' = Q $ \x -> p x <|> p' x -- Is there really sense in defining the Monad instance here? -- Order of operations doesn't mean anything here, I suppose? -- Well, it has influence on when the extraction stops when -- one of the predicates is not satisfied. -- -- On the other hand, it may be better if it's obvious that a -- monadic code means parsing here. -- instance Monad (Q a) where -- return = pure -- Q p >>= f = Q $ \x -> do -- y <- p x -- runQ (f y) x -- | Predicate which is always satisfied. true :: Q a a true = Q Just -- | Check if the given predicate is satisfied. satisfy :: (a -> Bool) -> Q a a satisfy p = Q $ \t -> if p t then Just t else Nothing