{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

-- | Ord properties
--
-- You will need @TypeApplications@ to use these.
module Test.Validity.Ord
  ( ordSpec,
    ordSpecOnGen,
    ordSpecOnArbitrary,
  )
where

import Data.Data
import Data.GenValidity
import Test.Hspec
import Test.QuickCheck
import Test.Validity.Functions
import Test.Validity.Relations
import Test.Validity.Utils

{-# ANN module "HLint: ignore Use <=" #-}

{-# ANN module "HLint: ignore Use >=" #-}

{-# ANN module "HLint: ignore Use <" #-}

{-# ANN module "HLint: ignore Use >" #-}

leTypeStr ::
  forall a.
  Typeable a =>
  String
leTypeStr :: forall a. Typeable a => String
leTypeStr = forall {k} (a :: k). Typeable a => String -> String
binRelStr @a String
"<="

geTypeStr ::
  forall a.
  Typeable a =>
  String
geTypeStr :: forall a. Typeable a => String
geTypeStr = forall {k} (a :: k). Typeable a => String -> String
binRelStr @a String
">="

ltTypeStr ::
  forall a.
  Typeable a =>
  String
ltTypeStr :: forall a. Typeable a => String
ltTypeStr = forall {k} (a :: k). Typeable a => String -> String
binRelStr @a String
"<"

gtTypeStr ::
  forall a.
  Typeable a =>
  String
gtTypeStr :: forall a. Typeable a => String
gtTypeStr = forall {k} (a :: k). Typeable a => String -> String
binRelStr @a String
">"

-- | Standard test spec for properties of Ord instances for valid values
--
-- Example usage:
--
-- > ordSpec @Int
ordSpec ::
  forall a.
  (Show a, Ord a, Typeable a, GenValid a) =>
  Spec
ordSpec :: forall a. (Show a, Ord a, Typeable a, GenValid a) => Spec
ordSpec = forall a.
(Show a, Ord a, Typeable a) =>
Gen a -> String -> (a -> [a]) -> Spec
ordSpecOnGen @a forall a. GenValid a => Gen a
genValid String
"valid" forall a. GenValid a => a -> [a]
shrinkValid

-- | Standard test spec for properties of Ord instances for arbitrary values
--
-- Example usage:
--
-- > ordSpecOnArbitrary @Int
ordSpecOnArbitrary ::
  forall a.
  (Show a, Ord a, Typeable a, Arbitrary a) =>
  Spec
ordSpecOnArbitrary :: forall a. (Show a, Ord a, Typeable a, Arbitrary a) => Spec
ordSpecOnArbitrary = forall a.
(Show a, Ord a, Typeable a) =>
Gen a -> String -> (a -> [a]) -> Spec
ordSpecOnGen @a forall a. Arbitrary a => Gen a
arbitrary String
"arbitrary" forall a. Arbitrary a => a -> [a]
shrink

-- | Standard test spec for properties of Ord instances for values generated by a given generator (and name for that generator).
--
-- Example usage:
--
-- > ordSpecOnGen ((* 2) <$> genValid @Int) "even"
ordSpecOnGen ::
  forall a.
  (Show a, Ord a, Typeable a) =>
  Gen a ->
  String ->
  (a -> [a]) ->
  Spec
ordSpecOnGen :: forall a.
(Show a, Ord a, Typeable a) =>
Gen a -> String -> (a -> [a]) -> Spec
ordSpecOnGen Gen a
gen String
genname a -> [a]
s =
  forall a. SpecWith a -> SpecWith a
parallel forall a b. (a -> b) -> a -> b
$ do
    let name :: String
name = forall {k} (a :: k). Typeable a => String
nameOf @a
        funlestr :: String
funlestr = forall a. Typeable a => String
leTypeStr @a
        fungestr :: String
fungestr = forall a. Typeable a => String
geTypeStr @a
        funltstr :: String
funltstr = forall a. Typeable a => String
ltTypeStr @a
        fungtstr :: String
fungtstr = forall a. Typeable a => String
gtTypeStr @a
        minmaxtstr :: String -> String
minmaxtstr = forall {k} (a :: k). Typeable a => String -> String
genDescr @(a -> a -> a)
        itProp :: String -> a -> SpecWith (Arg a)
itProp String
s_ =
          forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it forall a b. (a -> b) -> a -> b
$
            [String] -> String
unwords
              [ String
s_,
                String
"\"" forall a. [a] -> [a] -> [a]
++ String
genname,
                String
name forall a. [a] -> [a] -> [a]
++ String
"\"" forall a. [a] -> [a] -> [a]
++ String
"'s"
              ]
        cmple :: a -> a -> Bool
cmple = forall a. Ord a => a -> a -> Bool
(<=) @a
        cmpge :: a -> a -> Bool
cmpge = forall a. Ord a => a -> a -> Bool
(>=) @a
        cmplt :: a -> a -> Bool
cmplt = forall a. Ord a => a -> a -> Bool
(<) @a
        cmpgt :: a -> a -> Bool
cmpgt = forall a. Ord a => a -> a -> Bool
(>) @a
        gen2 :: Gen (a, a)
gen2 = (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
gen forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
gen
        gen3 :: Gen (a, a, a)
gen3 = (,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
gen forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
gen forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
gen
        s2 :: (a, a) -> [(a, a)]
s2 = forall a. (a -> [a]) -> (a, a) -> [(a, a)]
shrinkT2 a -> [a]
s
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (String
"Ord " forall a. [a] -> [a] -> [a]
++ String
name) forall a b. (a -> b) -> a -> b
$ do
      forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
funlestr forall a b. (a -> b) -> a -> b
$ do
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is reflexive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
reflexivityOnGen a -> a -> Bool
cmple Gen a
gen a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is antisymmetric for" forall a b. (a -> b) -> a -> b
$
          forall a.
(Show a, Eq a) =>
(a -> a -> Bool) -> Gen (a, a) -> (a -> [a]) -> Property
antisymmetryOnGens a -> a -> Bool
cmple Gen (a, a)
gen2 a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is transitive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
transitivityOnGens a -> a -> Bool
cmple Gen (a, a, a)
gen3 a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is equivalent to (\\a b -> compare a b /= GT) for" forall a b. (a -> b) -> a -> b
$
          forall a b c.
(Show a, Show b, Show c, Eq c) =>
(a -> b -> c)
-> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
equivalentOnGens2 a -> a -> Bool
cmple (\a
a a
b -> forall a. Ord a => a -> a -> Ordering
compare a
a a
b forall a. Eq a => a -> a -> Bool
/= Ordering
GT) Gen (a, a)
gen2 (a, a) -> [(a, a)]
s2
      forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
fungestr forall a b. (a -> b) -> a -> b
$ do
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is reflexive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
reflexivityOnGen a -> a -> Bool
cmpge Gen a
gen a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is antisymmetric for" forall a b. (a -> b) -> a -> b
$
          forall a.
(Show a, Eq a) =>
(a -> a -> Bool) -> Gen (a, a) -> (a -> [a]) -> Property
antisymmetryOnGens a -> a -> Bool
cmpge Gen (a, a)
gen2 a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is transitive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
transitivityOnGens a -> a -> Bool
cmpge Gen (a, a, a)
gen3 a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is equivalent to (\\a b -> compare a b /= LT) for" forall a b. (a -> b) -> a -> b
$
          forall a b c.
(Show a, Show b, Show c, Eq c) =>
(a -> b -> c)
-> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
equivalentOnGens2 a -> a -> Bool
cmpge (\a
a a
b -> forall a. Ord a => a -> a -> Ordering
compare a
a a
b forall a. Eq a => a -> a -> Bool
/= Ordering
LT) Gen (a, a)
gen2 (a, a) -> [(a, a)]
s2
      forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
funltstr forall a b. (a -> b) -> a -> b
$ do
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is antireflexive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
antireflexivityOnGen a -> a -> Bool
cmplt Gen a
gen a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is transitive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
transitivityOnGens a -> a -> Bool
cmplt Gen (a, a, a)
gen3 a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is equivalent to (\\a b -> compare a b == LT) for" forall a b. (a -> b) -> a -> b
$
          forall a b c.
(Show a, Show b, Show c, Eq c) =>
(a -> b -> c)
-> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
equivalentOnGens2 a -> a -> Bool
cmplt (\a
a a
b -> forall a. Ord a => a -> a -> Ordering
compare a
a a
b forall a. Eq a => a -> a -> Bool
== Ordering
LT) Gen (a, a)
gen2 (a, a) -> [(a, a)]
s2
      forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
fungtstr forall a b. (a -> b) -> a -> b
$ do
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is antireflexive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
antireflexivityOnGen a -> a -> Bool
cmpgt Gen a
gen a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is transitive for" forall a b. (a -> b) -> a -> b
$
          forall a.
Show a =>
(a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
transitivityOnGens a -> a -> Bool
cmpgt Gen (a, a, a)
gen3 a -> [a]
s
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is equivalent to (\\a b -> compare a b == GT) for" forall a b. (a -> b) -> a -> b
$
          forall a b c.
(Show a, Show b, Show c, Eq c) =>
(a -> b -> c)
-> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
equivalentOnGens2 a -> a -> Bool
cmpgt (\a
a a
b -> forall a. Ord a => a -> a -> Ordering
compare a
a a
b forall a. Eq a => a -> a -> Bool
== Ordering
GT) Gen (a, a)
gen2 (a, a) -> [(a, a)]
s2
      forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (String -> String
minmaxtstr String
"min") forall a b. (a -> b) -> a -> b
$ do
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is equivalent to (\\a b -> if a <= b then a else b) for" forall a b. (a -> b) -> a -> b
$
          forall a b c.
(Show a, Show b, Show c, Eq c) =>
(a -> b -> c)
-> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
equivalentOnGens2 forall a. Ord a => a -> a -> a
min (\a
a a
b -> if a
a forall a. Ord a => a -> a -> Bool
<= a
b then a
a else a
b) Gen (a, a)
gen2 (a, a) -> [(a, a)]
s2
      forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (String -> String
minmaxtstr String
"max") forall a b. (a -> b) -> a -> b
$ do
        forall {a}. Example a => String -> a -> SpecWith (Arg a)
itProp String
"is equivalent to (\\a b -> if a >= b then a else b) for" forall a b. (a -> b) -> a -> b
$
          forall a b c.
(Show a, Show b, Show c, Eq c) =>
(a -> b -> c)
-> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
equivalentOnGens2 forall a. Ord a => a -> a -> a
max (\a
a a
b -> if a
a forall a. Ord a => a -> a -> Bool
>= a
b then a
a else a
b) Gen (a, a)
gen2 (a, a) -> [(a, a)]
s2