{-# LANGUAGE ExistentialQuantification #-} module Database.Bolt.Extras.Internal.Condition ( Condition (..) , tautology , matches , itself ) where -- | Conditional expressions over type 'a' and its mappings. -- Supported operations: -- -- * equality check ':==' -- * disunction ':&&' -- * conjunction ':||' -- -- Typical usage: -- -- Say we have variable @var :: a@, a function @f :: a -> b@ and a value @val :: b@. -- Expression @f :== val@ acts as @f var == val@. -- -- Examples: -- -- > data D = D { fld1 :: Int -- > , fld2 :: String -- > , fld3 :: Double -- > } -- > -- > d = D 42 "noononno" 1.618 -- > d `matches` (fld1 :== 12 :&& fld2 :== "abc") -- > False -- > -- > d `matches` (fld1 :== 42 :|| fld3 == 1.0) -- > True -- infix 4 :== infixr 3 :&& infixr 2 :|| data Condition a = forall b. Eq b => (a -> b) :== b | Condition a :&& Condition a | Condition a :|| Condition a -- | Check whether data satisfies conditions on it. -- matches :: a -> Condition a -> Bool matches obj (transform :== ref) = transform obj == ref matches obj (u :&& v) = matches obj u && matches obj v matches obj (u :|| v) = matches obj u || matches obj v -- | Matching 'tautology' will always succeed. -- -- > whatever `matches` tautology == True -- -- Match is lazy: -- -- > undefined `matches` tautology == True -- tautology :: Condition a tautology = const True :== True -- | Object itself instead of its mappings is matched with help of this alias. -- -- > 42 `matches` (itself :== 42) == True -- > 42 `matches` (itself :== 41) == False -- itself :: a -> a itself = id