rpm-0.0.1: System/Rpm/Combinators.hs
{-|
'System.Rpm.Combinators' provides a mechanism for comparing
attributes of an Rpm against some sort of specification.
-}
module System.Rpm.Combinators
(
Rpm(..)
, RpmP
, zeroP
, oneP
, notP
, (.==.)
, (./=.)
, (.<=.)
, (.<.)
, (.>=.)
, (.>.)
, (.&&.)
, (.||.)
-- * Example: Common Uses
-- $exampleOfUse
) where
import System.Rpm.Info (RpmInfo(..))
type Rpm a = RpmInfo -> a
{-|
A predicate type that takes an 'RpmInfo' datatype and returns a
value of Bool depending on its evaluation.
-}
type RpmP = Rpm Bool
{-|
A standard lifting function.
-}
liftP :: (a -> a -> b) -- ^ The function to lift
-> Rpm a -- ^ The field to extract from 'RpmInfo'
-> a -- ^ Passed to the Second argument of the function
-> Rpm b -- ^ The result wrapped in 'Rpm'
liftP f g val rpmInfo= g rpmInfo `f` val
{-|
A more conventional lifting function.
-}
liftP2 :: (a -> b -> c)
-> Rpm a
-> Rpm b
-> Rpm c
liftP2 f g h rpmInfo = g rpmInfo `f` h rpmInfo
{-|
The 'zeroP' combinator, much like the 'oneP' combinator, is more
for completeness than anything.
-}
zeroP :: RpmP -- ^ The constant combinator that always returns
-- 'False' when run.
zeroP _ = False
oneP :: RpmP -- ^ The constant combinator that always returns 'False'
-- when run.
oneP _ = True
(.==.) :: Eq a => Rpm a -- ^ Some field of 'RpmInfo'
-> a -- ^ The value to check equality against
-> RpmP
(.==.) = liftP (==)
(./=.) :: Eq a => Rpm a -> a -> RpmP
(./=.) = liftP (/=)
(.<=.) :: Ord a => Rpm a -> a -> RpmP
(.<=.) = liftP (<=)
(.<.) :: Ord a => Rpm a -> a -> RpmP
(.<.) = liftP (<)
(.>=.) :: Ord a => Rpm a -> a -> RpmP
(.>=.) = liftP (>=)
(.>.) :: Ord a => Rpm a -> a -> RpmP
(.>.) = liftP (>)
{-|
@notP@ is used to negate its 'RpmP' when run.
-}
notP :: RpmP -- ^ Predicate to negate
-> RpmP -- ^ Negated predicate
notP p = not . p
{-|
This is a logical combinator used for constructing more complex
sequences of combinators by requiring both predicates to be true.
-}
(.&&.) :: RpmP
-> RpmP
-> RpmP
(.&&.) = liftP2 (&&)
{-|
This is a logical combinator used for constructing more complex
sequences of combinators by requiring one of the predicates to be true.
-}
(.||.) :: RpmP
-> RpmP
-> RpmP
(.||.) = liftP2 (||)
{-| $exampleOfUse
Example of use.
> main :: IO ()
> main = putStrLn "Hello"
-}
-- nameMatchesFilename :: RpmP
-- nameMatchesFilename rpmInfo = fileName .==. (name rpmInfo)
-- Then, to find where name doesn't match filename,
-- findAll (.!. nameMatchesFilename)
-- or, assertAll (nameMatchesFilename)
-- or, assertAll (buildHost .==. "my1.machine.org" .||. buildHost .==. "my2.machine.org")
-- Conditional predicate generation
-- ifThenElse :: RpmP -> RpmP -> RpmP
-- ifThenElse ( file `matchesP` "foo*" )
-- ( size .<=. 1234)
-- assertEqual .!. (.!. zeroP) == zeroP
-- assertEqual (.!. zeroP) == oneP