    {-# 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 a. Typeable a => String -> String
    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 a. Typeable a => String -> String
    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 a. Typeable a => String -> String
    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 a. Typeable a => String -> String
    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 Gen a
    forall a. GenValid a => Gen a
    genValid String
    "valid" a -> [a]
    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 Gen a
    forall a. Arbitrary a => Gen a
    arbitrary String
    "arbitrary" a -> [a]
    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 =
      Spec -> Spec
    forall a. SpecWith a -> SpecWith a
    parallel (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
        let name :: String
    name = forall a. Typeable a => String
    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 a. Typeable a => String -> String
    forall {k} (a :: k). Typeable a => String -> String
    genDescr @(a -> a -> a)
            itProp :: String -> a -> SpecWith (Arg a)
    itProp String
    s_ =
              String -> a -> SpecWith (Arg a)
    forall a.
    (HasCallStack, Example a) =>
    String -> a -> SpecWith (Arg a)
    it (String -> a -> SpecWith (Arg a))
    -> String -> a -> SpecWith (Arg a)
    forall a b. (a -> b) -> a -> b
    $
                [String] -> String
    unwords
                  [ String
    s_,
                    String
    "\"" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    genname,
                    String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "\"" String -> String -> 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 = (,) (a -> a -> (a, a)) -> Gen a -> Gen (a -> (a, a))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Gen a
    gen Gen (a -> (a, a)) -> Gen a -> Gen (a, a)
    forall a b. Gen (a -> b) -> Gen a -> Gen b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Gen a
    gen
            gen3 :: Gen (a, a, a)
    gen3 = (,,) (a -> a -> a -> (a, a, a)) -> Gen a -> Gen (a -> a -> (a, a, a))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Gen a
    gen Gen (a -> a -> (a, a, a)) -> Gen a -> Gen (a -> (a, a, a))
    forall a b. Gen (a -> b) -> Gen a -> Gen b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Gen a
    gen Gen (a -> (a, a, a)) -> Gen a -> Gen (a, a, a)
    forall a b. Gen (a -> b) -> Gen a -> Gen b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Gen a
    gen
            s2 :: (a, a) -> [(a, a)]
    s2 = (a -> [a]) -> (a, a) -> [(a, a)]
    forall a. (a -> [a]) -> (a, a) -> [(a, a)]
    shrinkT2 a -> [a]
    s
        String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String
    "Ord " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name) (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe String
    funlestr (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is reflexive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    forall a.
    Show a =>
    (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    reflexivityOnGen a -> a -> Bool
    cmple Gen a
    gen a -> [a]
    s
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is antisymmetric for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen (a, a) -> (a -> [a]) -> Property
    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
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is transitive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
    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
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is equivalent to (\\a b -> compare a b /= GT) for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> Gen (a, a)
    -> ((a, a) -> [(a, a)])
    -> Property
    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 -> a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare a
    a a
    b Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Ordering
    GT) Gen (a, a)
    gen2 (a, a) -> [(a, a)]
    s2
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe String
    fungestr (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is reflexive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    forall a.
    Show a =>
    (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    reflexivityOnGen a -> a -> Bool
    cmpge Gen a
    gen a -> [a]
    s
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is antisymmetric for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen (a, a) -> (a -> [a]) -> Property
    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
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is transitive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
    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
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is equivalent to (\\a b -> compare a b /= LT) for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> Gen (a, a)
    -> ((a, a) -> [(a, a)])
    -> Property
    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 -> a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare a
    a a
    b Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Ordering
    LT) Gen (a, a)
    gen2 (a, a) -> [(a, a)]
    s2
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe String
    funltstr (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is antireflexive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    forall a.
    Show a =>
    (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    antireflexivityOnGen a -> a -> Bool
    cmplt Gen a
    gen a -> [a]
    s
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is transitive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
    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
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is equivalent to (\\a b -> compare a b == LT) for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> Gen (a, a)
    -> ((a, a) -> [(a, a)])
    -> Property
    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 -> a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare a
    a a
    b Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ordering
    LT) Gen (a, a)
    gen2 (a, a) -> [(a, a)]
    s2
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe String
    fungtstr (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is antireflexive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    forall a.
    Show a =>
    (a -> a -> Bool) -> Gen a -> (a -> [a]) -> Property
    antireflexivityOnGen a -> a -> Bool
    cmpgt Gen a
    gen a -> [a]
    s
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is transitive for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
    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
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is equivalent to (\\a b -> compare a b == GT) for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> Gen (a, a)
    -> ((a, a) -> [(a, a)])
    -> Property
    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 -> a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare a
    a a
    b Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ordering
    GT) Gen (a, a)
    gen2 (a, a) -> [(a, a)]
    s2
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String -> String
    minmaxtstr String
    "min") (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is equivalent to (\\a b -> if a <= b then a else b) for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> a)
    -> (a -> a -> a) -> Gen (a, a) -> ((a, a) -> [(a, a)]) -> Property
    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 -> a
    forall a. Ord a => a -> a -> a
    min (\a
    a a
    b -> if a
    a a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    b then a
    a else a
    b) Gen (a, a)
    gen2 (a, a) -> [(a, a)]
    s2
          String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String -> String
    minmaxtstr String
    "max") (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $ do
            String -> Property -> SpecM (Arg Property) ()
    forall {a}. Example a => String -> a -> SpecWith (Arg a)
    itProp String
    "is equivalent to (\\a b -> if a >= b then a else b) for" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
              (a -> a -> a)
    -> (a -> a -> a) -> Gen (a, a) -> ((a, a) -> [(a, a)]) -> Property
    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 -> a
    forall a. Ord a => a -> a -> a
    max (\a
    a a
    b -> if a
    a a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    >= a
    b then a
    a else a
    b) Gen (a, a)
    gen2 (a, a) -> [(a, a)]
    s2