module Test.LeanCheck.Utils.Operators
(
(===), (====)
, (&&&), (&&&&)
, (|||), (||||)
, idempotent
, identity
, neverIdentity
, commutative
, associative
, distributive
, symmetric2
, transitive
, reflexive
, irreflexive
, symmetric
, asymmetric
, antisymmetric
, equivalence
, partialOrder
, strictPartialOrder
, totalOrder
, strictTotalOrder
, comparison
, (=$), ($=)
, (=|), (|=)
, okEq
, okOrd
, okEqOrd
, okNum
)
where
import Test.LeanCheck ((==>))
import Data.List (elem)
combine :: (b -> c -> d) -> (a -> b) -> (a -> c) -> (a -> d)
combine op f g = \x -> f x `op` g x
(===) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool
(===) = combine (==)
infix 4 ===
(====) :: Eq c => (a -> b -> c) -> (a -> b -> c) -> a -> b -> Bool
(====) = combine (===)
infix 4 ====
(&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
(&&&) = combine (&&)
infixr 3 &&&
(&&&&) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool
(&&&&) = combine (&&&)
infixr 3 &&&&
(&&&&&) :: (a -> b -> c -> Bool) -> (a -> b -> c -> Bool) -> a -> b -> c -> Bool
(&&&&&) = combine (&&&&)
infixr 3 &&&&&
(|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
(|||) = combine (||)
infixr 2 |||
(||||) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool
(||||) = combine (|||)
infixr 2 ||||
commutative :: Eq b => (a -> a -> b) -> a -> a -> Bool
commutative o = \x y -> x `o` y == y `o` x
associative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool
associative o = \x y z -> x `o` (y `o` z) == (x `o` y) `o` z
distributive :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool
distributive o o' = \x y z -> x `o` (y `o'` z) == (x `o` y) `o'` (x `o` z)
symmetric2 :: Eq b => (a -> a -> b) -> (a -> a -> b) -> a -> a -> Bool
symmetric2 (+-) (-+) = \x y -> x +- y == y -+ x
transitive :: (a -> a -> Bool) -> a -> a -> a -> Bool
transitive o = \x y z -> x `o` y && y `o` z ==> x `o` z
reflexive :: (a -> a -> Bool) -> a -> Bool
reflexive o = \x -> x `o` x
irreflexive :: (a -> a -> Bool) -> a -> Bool
irreflexive o = \x -> not $ x `o` x
symmetric :: (a -> a -> Bool) -> a -> a -> Bool
symmetric = commutative
antisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool
antisymmetric r = \x y -> x `r` y && y `r` x ==> x == y
asymmetric :: (a -> a -> Bool) -> a -> a -> Bool
asymmetric r = \x y -> x `r` y ==> not (y `r` x)
equivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool
equivalence (==) = \x y z -> reflexive (==) x
&& symmetric (==) x y
&& transitive (==) x y z
partialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
partialOrder (<=) = \x y z -> reflexive (<=) x
&& antisymmetric (<=) x y
&& transitive (<=) x y z
strictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool
strictPartialOrder (<) = \x y z -> irreflexive (<) x
&& asymmetric (<) x y
&& transitive (<) x y z
totalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
totalOrder (<=) = \x y z -> (x <= y || y <= x)
&& antisymmetric (<=) x y
&& transitive (<=) x y z
strictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
strictTotalOrder (<) = \x y z -> (x /= y ==> x < y || y < x)
&& irreflexive (<) x
&& asymmetric (<) x y
&& transitive (<) x y z
comparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool
comparison compare = \x y z -> equivalence (===) x y z
&& irreflexive (<) x
&& transitive (<) x y z
&& symmetric2 (<) (>) x y
where
x === y = x `compare` y == EQ
x =/= y = x `compare` y /= EQ
x < y = x `compare` y == LT
x > y = x `compare` y == GT
idempotent :: Eq a => (a -> a) -> a -> Bool
idempotent f = f . f === f
identity :: Eq a => (a -> a) -> a -> Bool
identity f = f === id
neverIdentity :: Eq a => (a -> a) -> a -> Bool
neverIdentity = (not .) . identity
okEq :: Eq a => a -> a -> a -> Bool
okEq = equivalence (==)
okOrd :: Ord a => a -> a -> a -> Bool
okOrd x y z = totalOrder (<=) x y z
&& comparison compare x y z
&& (x <= y) == ((x `compare` y) `elem` [LT,EQ])
okEqOrd :: (Eq a, Ord a) => a -> a -> a -> Bool
okEqOrd x y z = okEq x y z
&& okOrd x y z
&& (x == y) == (x `compare` y == EQ)
okNum :: (Eq a, Num a) => a -> a -> a -> Bool
okNum x y z = commutative (+) x y
&& commutative (*) x y
&& associative (+) x y z
&& associative (*) x y z
&& distributive (*) (+) x y z
&& idempotent (+0) x
&& idempotent (*1) x
&& idempotent abs x
&& idempotent signum x
&& negate (negate x) == x
&& abs x * signum x == x
&& x - x == 0
(=$) :: Eq b => a -> (a -> b) -> a -> Bool
(x =$ f) y = f x == f y
infixl 4 =$
($=) :: (a -> Bool) -> a -> Bool
($=) = ($)
infixl 4 $=
(=|) :: Eq a => [a] -> Int -> [a] -> Bool
xs =| n = xs =$ take n
infixl 4 =|
(|=) :: (a -> Bool) -> a -> Bool
(|=) = ($)
infixl 4 |=