    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE ScopedTypeVariables #-}

    module Test.Validity.Relations.Transitivity
      ( transitiveOnElems,
        transitivityOnGens,
        transitivity,
        transitivityOnArbitrary,
      )
    where

    import Data.GenValidity
    import Test.QuickCheck
    import Test.Validity.Property.Utils

    -- |
    --
    -- \[
    --   Transitive(\prec)
    --   \quad\equiv\quad
    --   \forall a, b, c: ((a \prec b) \wedge (b \prec c)) \Rightarrow (a \prec c)
    -- \]
    transitiveOnElems ::
      -- | A relation
      (a -> a -> Bool) ->
      a ->
      a ->
      -- | Three elements
      a ->
      Bool
    transitiveOnElems :: forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
    transitiveOnElems a -> a -> Bool
    func a
    a a
    b a
    c = (a -> a -> Bool
    func a
    a a
    b Bool -> Bool -> Bool
    && a -> a -> Bool
    func a
    b a
    c) Bool -> Bool -> Bool
    ===> a -> a -> Bool
    func a
    a a
    c

    transitivityOnGens ::
      Show a => (a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
    transitivityOnGens :: forall a.
    Show a =>
    (a -> a -> Bool) -> Gen (a, a, a) -> (a -> [a]) -> Property
    transitivityOnGens a -> a -> Bool
    func Gen (a, a, a)
    gen a -> [a]
    s =
      Gen (a, a, a)
    -> ((a, a, a) -> [(a, a, a)]) -> ((a, a, a) -> Bool) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen (a, a, a)
    gen ((a -> [a]) -> (a, a, a) -> [(a, a, a)]
    forall a. (a -> [a]) -> (a, a, a) -> [(a, a, a)]
    shrinkT3 a -> [a]
    s) (((a, a, a) -> Bool) -> Property)
    -> ((a, a, a) -> Bool) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, a
    b, a
    c) -> (a -> a -> Bool) -> a -> a -> a -> Bool
    forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
    transitiveOnElems a -> a -> Bool
    func a
    a a
    b a
    c

    -- |
    --
    -- prop> transitivity ((>) :: Int -> Int -> Bool)
    -- prop> transitivity ((>=) :: Int -> Int -> Bool)
    -- prop> transitivity ((==) :: Int -> Int -> Bool)
    -- prop> transitivity ((<=) :: Int -> Int -> Bool)
    -- prop> transitivity ((<) :: Int -> Int -> Bool)
    -- prop> transitivity (Data.List.isPrefixOf :: [Int] -> [Int] -> Bool)
    -- prop> transitivity (Data.List.isSuffixOf :: [Int] -> [Int] -> Bool)
    -- prop> transitivity (Data.List.isInfixOf :: [Int] -> [Int] -> Bool)
    transitivity :: (Show a, GenValid a) => (a -> a -> Bool) -> Property
    transitivity :: forall a. (Show a, GenValid a) => (a -> a -> Bool) -> Property
    transitivity a -> a -> Bool
    func = (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
    func Gen (a, a, a)
    forall a. GenValid a => Gen a
    genValid a -> [a]
    forall a. GenValid a => a -> [a]
    shrinkValid

    -- |
    --
    -- prop> transitivityOnArbitrary ((>) :: Int -> Int -> Bool)
    -- prop> transitivityOnArbitrary ((>=) :: Int -> Int -> Bool)
    -- prop> transitivityOnArbitrary ((==) :: Int -> Int -> Bool)
    -- prop> transitivityOnArbitrary ((<=) :: Int -> Int -> Bool)
    -- prop> transitivityOnArbitrary ((<) :: Int -> Int -> Bool)
    -- prop> transitivityOnArbitrary (Data.List.isPrefixOf :: [Int] -> [Int] -> Bool)
    -- prop> transitivityOnArbitrary (Data.List.isSuffixOf :: [Int] -> [Int] -> Bool)
    -- prop> transitivityOnArbitrary (Data.List.isInfixOf :: [Int] -> [Int] -> Bool)
    transitivityOnArbitrary :: (Show a, Arbitrary a) => (a -> a -> Bool) -> Property
    transitivityOnArbitrary :: forall a. (Show a, Arbitrary a) => (a -> a -> Bool) -> Property
    transitivityOnArbitrary a -> a -> Bool
    func = (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
    func Gen (a, a, a)
    forall a. Arbitrary a => Gen a
    arbitrary a -> [a]
    forall a. Arbitrary a => a -> [a]
    shrink