-- |
-- Module      : Test.LeanCheck.Utils.Operators
-- Copyright   : (c) 2015-2024 Rudy Matela
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : Rudy Matela <rudy@matela.com.br>
--
-- This module is part of LeanCheck,
-- a simple enumerative property-based testing library.
--
-- Some operators for property-based testing.
module Test.LeanCheck.Utils.Operators
  (

  -- * Combining properties
    (==>)
  , (===), (====)
  , (&&&), (&&&&), (&&&&&)
  , (|||), (||||)

  -- * Properties of unary functions
  , isIdempotent
  , isIdentity
  , isNeverIdentity

  -- * Properties of operators (binary functions)
  , isCommutative
  , isAssociative
  , isDistributiveOver
  , isLeftDistributiveOver
  , isRightDistributiveOver
  , isFlipped

  -- * Properties of relations (binary functions returning truth values)
  , isTransitive
  , isReflexive
  , isIrreflexive
  , isSymmetric
  , isAsymmetric
  , isAntisymmetric

  -- * Properties of order relations
  , isEquivalence
  , isPartialOrder
  , isStrictPartialOrder
  , isTotalOrder
  , isStrictTotalOrder
  , isComparison

  -- * Ternary comparison operators
  , (=$), ($=)
  , (=|), (|=)

  -- * Properties for typeclass instances
  , okEq
  , okOrd
  , okEqOrd
  , okNum
  , okNumNonNegative

  -- * Deprecated functions
  , idempotent
  , identity
  , neverIdentity
  , commutative
  , associative
  , distributive
  , symmetric2
  , transitive
  , reflexive
  , irreflexive
  , symmetric
  , asymmetric
  , antisymmetric
  , equivalence
  , partialOrder
  , strictPartialOrder
  , totalOrder
  , strictTotalOrder
  , comparison
  )
where

import Test.LeanCheck ((==>))

combine :: (b -> c -> d) -> (a -> b) -> (a -> c) -> (a -> d)
combine (?) f g  =  \x -> f x ? g x

-- Uneeded, just food for thought:
--
-- > combine2 :: (c -> d -> e)
-- >          -> (a -> b -> c)
-- >          -> (a -> b -> d)
-- >          -> (a -> b -> e)
--
-- Two possible implementations:
-- > combine2 op f g  =  \x y -> f x y `op` g x y
-- > combine2  =  combine . combine

-- | Allows building equality properties between functions.
--
-- > prop_id_idempotent  =  id === id . id
--
-- > > check $ id === (+0)
-- > +++ OK, passed 200 tests.
--
-- > > check $ id === id . id
-- > +++ OK, passed 1 tests (exhausted).
--
-- > > check $ id === (+1)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0
(===) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool
(===)  =  combine (==)
infix 4 ===

-- | Allows building equality properties between two-argument functions.
--
-- > > holds 100 $ const ==== asTypeOf
-- > True
--
-- > > holds 100 $ (+) ==== flip (+)
-- > True
--
-- > > holds 100 $ (+) ==== (*)
-- > False
(====) :: Eq c => (a -> b -> c) -> (a -> b -> c) -> a -> b -> Bool
(====)  =  combine (===)
infix 4 ====

-- | And ('&&') operator over one-argument properties.
--
-- Allows building conjuntions between one-argument properties:
--
-- > > holds 100 $ id === (+0) &&& id === (id . id)
-- > True
(&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
(&&&)  =  combine (&&)
infixr 3 &&&

-- | And ('&&') operator over two-argument properties.
--
-- Allows building conjuntions between two-argument properties:
--
-- > > holds 100 $ (+) ==== flip (+) &&&& (+) ==== (*)
-- > False
(&&&&) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool
(&&&&)  =  combine (&&&)
infixr 3 &&&&

-- | And operator over three-argument properties.
(&&&&&) :: (a -> b -> c -> Bool) -> (a -> b -> c -> Bool) -> a -> b -> c -> Bool
(&&&&&)  =  combine (&&&&)
infixr 3 &&&&&

-- | Or ('||') operator over one-argument properties.
--
-- Allows building disjunctions between one-argument properties:
--
-- > > holds 100 $ id === (+0) ||| id === (id . id)
-- > True
(|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
(|||)  =  combine (||)
infixr 2 |||

-- | Or ('||') operator over two-argument properties.
--
-- Allows building conjuntions between two-argument properties:
--
-- > > holds 100 $ (+) ==== flip (+) |||| (+) ==== (*)
-- > True
(||||) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool
(||||)  =  combine (|||)
infixr 2 ||||

-- | Is a given operator commutative?  @x + y = y + x@
--
-- > > check $ isCommutative (+)
-- > +++ OK, passed 200 tests.
--
-- > > import Data.List
-- > > check $ isCommutative (union :: [Int]->[Int]->[Int])
-- > *** Failed! Falsifiable (after 4 tests):
-- > [] [0,0]
isCommutative :: Eq b => (a -> a -> b) -> a -> a -> Bool
isCommutative (?)  =  \x y -> x ? y == y ? x

-- | Is a given operator associative?  @x + (y + z) = (x + y) + z@
--
-- > > check $ isAssociative (+)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isAssociative (-)
-- > *** Failed! Falsifiable (after 2 tests):
-- > 0 0 1
isAssociative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool
isAssociative (?)  =  \x y z -> x ? (y ? z) == (x ? y) ? z

-- | Does the first operator, left-distributes over the second?
--
-- This is an alias to 'isLeftDistributiveOver'.
isDistributiveOver :: Eq a
                   => (a -> a -> a) -> (a -> a -> a)
                   -> a -> a -> a -> Bool
isDistributiveOver  =  isLeftDistributiveOver

-- | Does the first operator, left-distributes over the second?
--   @x * (y + z) = (x * y) + (x * z)@
--
-- > > check $ (*) `isLeftDistributiveOver` (+)
-- > +++ OK, passed 200 tests.
--
-- > > check $ (+) `isLeftDistributiveOver` (*)
-- > *** Failed! Falsifiable (after 8 tests):
-- > 1 0 1
isLeftDistributiveOver :: Eq a
                       => (a -> a -> a) -> (a -> a -> a)
                       -> a -> a -> a -> Bool
(?) `isLeftDistributiveOver` (#)  =  \x y z -> x ? (y # z) == (x ? y) # (x ? z)

-- | Does the first operator, right-distributes over the second?
--   @(y + z) * x = (y * x) + (z * x)@
--
-- > > check $ (*) `isRightDistributiveOver` (+)
-- > +++ OK, passed 200 tests.
--
-- > > check $ (+) `isRightDistributiveOver` (*)
-- > *** Failed! Falsifiable (after 8 tests):
-- > 1 0 1
isRightDistributiveOver :: Eq a
                        => (a -> a -> a) -> (a -> a -> a)
                        -> a -> a -> a -> Bool
(?) `isRightDistributiveOver` (#)  =  \x y z -> (y # z) ? x == (y ? x) # (z ? x)

-- | Are two operators 'flip'ped versions of each other?
--
-- > > check $ ((<) `isFlipped` (>) :: Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ ((<=) `isFlipped` (>=) :: Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ ((<) `isFlipped` (>=) :: Int -> Int -> Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0
--
-- > > check $ ((<=) `isFlipped` (>) :: Int -> Int -> Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0
isFlipped :: Eq c => (a -> b -> c) -> (b -> a -> c) -> a -> b -> Bool
(+-) `isFlipped` (-+)  =  \x y -> x +- y == y -+ x

-- | Is a given relation transitive?
--
-- A relation is transitive when
-- if a is related to b then b is related to c.
--
-- > > check $ isTransitive ((==) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isTransitive ((/=) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 3 tests):
-- > 0 1 0
isTransitive :: (a -> a -> Bool) -> a -> a -> a -> Bool
isTransitive (?)  =  \x y z -> x ? y && y ? z ==> x ? z

-- | Is a given relation reflexive?
--
-- A relation is reflexive when
-- an element is always related to itself.
--
-- > > check $ isReflexive ((==) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isReflexive ((/=) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0
isReflexive :: (a -> a -> Bool) -> a -> Bool
isReflexive (?)  =  \x -> x ? x

-- | Is a given relation irreflexive?
--
-- A given relation is irreflexive or anti-reflexive
-- when an element is _never_ related to itself.
--
-- This is /not/ the negation of 'isReflexive'.
--
-- > > check $ isIrreflexive ((==) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0
--
-- > > check $ isIrreflexive ((/=) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
isIrreflexive :: (a -> a -> Bool) -> a -> Bool
isIrreflexive (?)  =  \x -> not $ x ? x

-- | Is a given relation symmetric?
--
-- A relation is symmetric when
-- if a is related to b, then b is related to a.
--
-- > > check $ isSymmetric (&&)
-- > +++ OK, passed 4 tests (exhausted).
--
-- > > check $ isSymmetric (==>)
-- > *** Failed! Falsifiable (after 2 tests):
-- > False True
--
-- This is a type-restricted version of 'isCommutative'.
isSymmetric :: (a -> a -> Bool) -> a -> a -> Bool
isSymmetric  =  isCommutative

-- | Is a given relation antisymmetric?
--
-- Not to be confused with 'isAsymmetric'.
-- Not to be confused with the negation of 'isSymmetric'.
--
-- > > check $ isAntisymmetric ((<=) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isAntisymmetric ((/=) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 2 tests):
-- > 0 1
isAntisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool
isAntisymmetric (?)  =  \x y -> x ? y && y ? x ==> x == y

-- | Is a given relation asymmetric?
--
-- Not to be confused with not 'isSymmetric' and 'isAntisymmetric'.
--
-- > > check $ isAsymmetric ((<=) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0
--
-- > > check $ isAsymmetric ((<) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
isAsymmetric :: (a -> a -> Bool) -> a -> a -> Bool
isAsymmetric (?)  =  \x y -> x ? y ==> not (y ? x)

-- | Is the given binary relation an equivalence?
--
-- In other words,
-- is the given relation reflexive, symmetric and transitive?
--
-- > > check (isEquivalence (==) :: Int -> Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check (isEquivalence (<=) :: Int -> Int -> Int -> Bool)
-- > *** Failed! Falsifiable (after 3 tests):
-- > 0 1 0
--
-- Or, using "Test.LeanCheck.Utils.TypeBinding":
--
-- > > check $ isEquivalence (<=) -:> int
-- > *** Failed! Falsifiable (after 3 tests):
-- > 0 1 0
isEquivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool
isEquivalence (==)  =  \x y z -> isReflexive  (==) x
                              && isSymmetric  (==) x y
                              && isTransitive (==) x y z

-- | Is the given binary relation a partial order?
--
-- In other words,
-- is the given relation reflexive, antisymmetric and transitive?
--
-- > > check $ isPartialOrder ((<) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0 0
--
-- > > check $ isPartialOrder ((<=) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isPartialOrder isSubsetOf
-- > +++ OK, passed 200 tests.
isPartialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
isPartialOrder (<=)  =  \x y z -> isReflexive     (<=) x
                               && isAntisymmetric (<=) x y
                               && isTransitive    (<=) x y z

-- | Is the given binary relation a strict partial order?
--
-- In other words,
-- is the given relation irreflexive, asymmetric and transitive?
--
-- > > check $ isStrictPartialOrder ((<) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isStrictPartialOrder ((<=) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0 0
isStrictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool
isStrictPartialOrder (<)  =  \x y z -> isIrreflexive (<) x
                                    && isAsymmetric  (<) x y -- implied?
                                    && isTransitive  (<) x y z

-- | Is the given binary relation a total order?
--
-- > > check $ isTotalOrder ((<) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0 0
-- > > check $ isTotalOrder ((<=) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
isTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
isTotalOrder (<=)  =  \x y z -> (x <= y || y <= x)
                             && isAntisymmetric (<=) x y
                             && isTransitive    (<=) x y z

-- | Is the given binary relation a strict total order?
--
-- > > check $ isStrictTotalOrder ((<=) :: Int->Int->Bool)
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0 0 0
--
-- > > check $ isStrictTotalOrder ((<) :: Int->Int->Bool)
-- > +++ OK, passed 200 tests.
isStrictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
isStrictTotalOrder (<)  =  \x y z -> (x /= y ==> x < y || y < x)
                                  && isIrreflexive (<) x
                                  && isAsymmetric  (<) x y -- implied?
                                  && isTransitive  (<) x y z

-- | Does the given 'compare' function follow the required properties?
--
-- This is useful for testing custom 'Ord' instances.
--
-- > > check $ isComparison (compare :: Int->Int->Ordering)
-- > +++ OK, passed 200 tests.
isComparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool
isComparison compare  =  \x y z -> isEquivalence (===) x y z
                                && isIrreflexive (<) x
                                && isTransitive  (<) x y z
                                && ((<) `isFlipped` (>)) x y
  where
  x === y  =  x `compare` y == EQ
  x  <  y  =  x `compare` y == LT
  x  >  y  =  x `compare` y == GT

-- | Is the given function idempotent? @f (f x) == x@
--
-- > > check $ isIdempotent abs
-- > +++ OK, passed 200 tests.
--
-- > > check $ isIdempotent sort
-- > +++ OK, passed 200 tests.
--
-- > > check $ isIdempotent negate
-- > *** Failed! Falsifiable (after 2 tests):
-- > 1
isIdempotent :: Eq a => (a -> a) -> a -> Bool
isIdempotent f  =  f . f === f

-- | Is the given function an identity? @f x == x@
--
-- > > check $ isIdentity (+0)
-- > +++ OK, passed 200 tests.
--
-- > > check $ isIdentity (sort :: [()]->[()])
-- > +++ OK, passed 200 tests.
--
-- > > check $ isIdentity (not . not)
-- > +++ OK, passed 2 tests (exhausted).
isIdentity :: Eq a => (a -> a) -> a -> Bool
isIdentity f  =  f === id

-- | Is the given function never an identity? @f x /= x@
--
-- > > check $ neverIdentity not
-- > +++ OK, passed 2 tests (exhausted).
--
-- > > check $ neverIdentity negate
-- > *** Failed! Falsifiable (after 1 tests):
-- > 0
--
-- Note: this is not the same as not being an 'identity'.
isNeverIdentity :: Eq a => (a -> a) -> a -> Bool
isNeverIdentity  =  (not .) . isIdentity

-- | Is this 'Eq' instance valid?
--
-- This is useful for testing your custom 'Eq' instances
-- against required properties.
--
-- In particular,
-- this function tests that '==' is an equivalence
-- and that '/=' is the negation of '=='.
--
-- > > check $ (okEq :: Int -> Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ (okEq :: Bool -> Bool -> Bool -> Bool)
-- > +++ OK, passed 8 tests (exhausted).
okEq :: Eq a => a -> a -> a -> Bool
okEq x y z  =  isEquivalence (==) x y z
            && (x /= y) == not (x == y)

-- | Is this 'Ord' instance valid?
--
-- This is useful for testing your custom 'Ord' instances
-- against required properties.
--
-- > > check $ (okOrd :: Int -> Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ (okOrd :: Bool -> Bool -> Bool -> Bool)
-- > +++ OK, passed 8 tests (exhausted).
okOrd :: Ord a => a -> a -> a -> Bool
okOrd x y z  =  isTotalOrder (<=) x y z
             && isComparison compare x y z
             && (x <= y) == ((x `compare` y) `elem` [LT,EQ])

-- | Is this 'Eq' and 'Ord' instance valid and consistent?
--
-- This is useful for testing your custom 'Eq' and 'Ord' instances
-- against required properties.
--
-- > > check $ (okEqOrd :: Int -> Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- > > check $ (okEqOrd :: Bool -> Bool -> Bool -> Bool)
-- > +++ OK, passed 8 tests (exhausted).
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) -- consistent instances

-- | Like 'okNum' but restricted to zero and positives.
--
-- > > check (okNumNonNegative :: Natural -> Natural -> Natural -> Bool)
-- > +++ OK, passed 200 tests.
okNumNonNegative :: (Eq a, Num a) => a -> a -> a -> Bool
okNumNonNegative x y z  =  isCommutative (+) x y
                        && isCommutative (*) x y
                        && isAssociative (+) x y z
                        && isAssociative (*) x y z
                        && ((*) `isDistributiveOver` (+)) x y z
                        && isIdempotent (+0) x
                        && isIdempotent (*1) x
                        && isIdempotent abs x
                        && isIdempotent signum x
                        && abs x * signum x == x

-- | Is this 'Num' instance valid?
--
-- This is useful for testing your custom 'Num' instances
-- against required properties.
--
-- > > check (okNum :: Int -> Int -> Int -> Bool)
-- > +++ OK, passed 200 tests.
--
-- Double is /mostly/ valid, but not /entirely/ valid:
--
-- > > check (okNum :: Double -> Double -> Double -> Bool)
-- > *** Failed! Falsifiable (after 6 tests):
-- 0.0 0.0 Infinity
okNum :: (Eq a, Num a) => a -> a -> a -> Bool
okNum x y z  =  okNumNonNegative x y z
             && negate (negate x) == x
             && x - x == 0

-- | Equal under, a ternary operator with the same fixity as '=='.
--
-- > x =$ f $= y  =  f x == f y
--
-- > > [1,2,3,4,5] =$ take 2 $= [1,2,4,8,16]
-- > True
--
-- > > [1,2,3,4,5] =$ take 3 $= [1,2,4,8,16]
-- > False
--
-- > > [1,2,3] =$ sort $= [3,2,1]
-- > True
--
-- > > 42 =$ (`mod` 10) $= 16842
-- > True
--
-- > > 42 =$ (`mod`  9) $= 16842
-- > False
--
-- > > 'a' =$ isLetter $= 'b'
-- > True
--
-- > > 'a' =$ isLetter $= '1'
-- > False
(=$) :: Eq b => a -> (a -> b) -> a -> Bool
(x =$ f) y  =  f x == f y
infixl 4 =$

-- | See '=$'
($=) :: (a -> Bool) -> a -> Bool
($=)  =  ($)
infixl 4 $=

-- | Check if two lists are equal for @n@ values.
--   This operator has the same fixity of '=='.
--
-- > xs =| n |= ys  =  take n xs == take n ys
--
-- > [1,2,3,4,5] =| 2 |= [1,2,4,8,16] -- > True
-- > [1,2,3,4,5] =| 3 |= [1,2,4,8,16] -- > False
(=|) :: Eq a => [a] -> Int -> [a] -> Bool
xs =| n  =  xs =$ take n
infixl 4 =|

-- | See '=|'
(|=) :: (a -> Bool) -> a -> Bool
(|=)  =  ($)
infixl 4 |=


-- | Deprecated: use 'isCommutative'.
{-# DEPRECATED commutative "Use isCommutative." #-}
commutative :: Eq b => (a -> a -> b) -> a -> a -> Bool
commutative  =  isCommutative

-- | Deprecated: use 'isAssociative'.
{-# DEPRECATED associative "Use isAssociative." #-}
associative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool
associative  =  isAssociative

-- | Deprecated: use 'isDistributiveOver'.
{-# DEPRECATED distributive "Use isDistributiveOver." #-}
distributive :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool
distributive  =  isDistributiveOver

-- | Deprecated: use 'isFlipped'.
{-# DEPRECATED symmetric2 "Use isFlipped." #-}
symmetric2 :: Eq c => (a -> b -> c) -> (b -> a -> c) -> a -> b -> Bool
symmetric2  =  isFlipped

-- | Deprecated: use 'isTransitive'.
{-# DEPRECATED transitive "Use isTransitive." #-}
transitive :: (a -> a -> Bool) -> a -> a -> a -> Bool
transitive  =  isTransitive

-- | Deprecated: use 'isReflexive'.
{-# DEPRECATED reflexive "Use isReflexive." #-}
reflexive :: (a -> a -> Bool) -> a -> Bool
reflexive  =  isReflexive

-- | Deprecated: use 'isIrreflexive'.
{-# DEPRECATED irreflexive "Use isIrreflexive." #-}
irreflexive :: (a -> a -> Bool) -> a -> Bool
irreflexive  =  isIrreflexive

-- | Deprecated: use 'isSymmetric'.
{-# DEPRECATED symmetric "Use isSymmetric." #-}
symmetric :: (a -> a -> Bool) -> a -> a -> Bool
symmetric  =  isSymmetric

-- | Deprecated: use 'isAntisymmetric'.
{-# DEPRECATED antisymmetric "Use isAntisymmetric." #-}
antisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool
antisymmetric  =  isAntisymmetric

-- | Deprecated: use 'isAsymmetric'.
{-# DEPRECATED asymmetric "Use isAsymmetric." #-}
asymmetric :: (a -> a -> Bool) -> a -> a -> Bool
asymmetric  =  isAsymmetric

-- | Deprecated: use 'isEquivalence'.
{-# DEPRECATED equivalence "Use isEquivalence." #-}
equivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool
equivalence  =  isEquivalence

-- | Deprecated: use 'isPartialOrder'.
{-# DEPRECATED partialOrder "Use isPartialOrder." #-}
partialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
partialOrder  =  isPartialOrder

-- | Deprecated: use 'isStrictPartialOrder'.
{-# DEPRECATED strictPartialOrder "Use isStrictPartialOrder." #-}
strictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool
strictPartialOrder  =  isStrictPartialOrder

-- | Deprecated: use 'isTotalOrder'.
{-# DEPRECATED totalOrder "Use isTotalOrder." #-}
totalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
totalOrder  =  isTotalOrder

-- | Deprecated: use 'isStrictTotalOrder'.
{-# DEPRECATED strictTotalOrder "Use isStrictTotalOrder." #-}
strictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
strictTotalOrder  =  isStrictTotalOrder

-- | Deprecated: use 'isComparison'.
{-# DEPRECATED comparison "Use isComparison." #-}
comparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool
comparison  =  isComparison

-- | Deprecated: use 'isIdempotent'.
{-# DEPRECATED idempotent "Use isIdempotent." #-}
idempotent :: Eq a => (a -> a) -> a -> Bool
idempotent  =  isIdempotent

-- | Deprecated: use 'isIdentity'.
{-# DEPRECATED identity "Use isIdentity." #-}
identity :: Eq a => (a -> a) -> a -> Bool
identity  =  isIdentity

-- | Deprecated: use 'isNeverIdentity'.
{-# DEPRECATED neverIdentity "Use isNeverIdentity." #-}
neverIdentity :: Eq a => (a -> a) -> a -> Bool
neverIdentity  =  isNeverIdentity
