    {-# LANGUAGE CPP #-}
    {-# LANGUAGE ScopedTypeVariables #-}

    #if HAVE_QUANTIFIED_CONSTRAINTS
    {-# LANGUAGE QuantifiedConstraints #-}
    #endif

    {-# OPTIONS_GHC -Wall #-}

    module Test.QuickCheck.Classes.Semigroupoid
      (
    #if defined(HAVE_SEMIGROUPOIDS) && defined(HAVE_BINARY_LAWS)
        semigroupoidLaws
      , commutativeSemigroupoidLaws
    #endif
      ) where

    #if defined(HAVE_SEMIGROUPOIDS) && defined(HAVE_BINARY_LAWS)
    import Prelude hiding (id, (.))
    import Data.Semigroupoid (Semigroupoid(..))
    import Test.QuickCheck hiding ((.&.))
    import Data.Functor.Classes (Eq2,Show2)
    import Test.QuickCheck.Property (Property)

    import Test.QuickCheck.Classes.Internal

    -- | Tests the following 'Semigroupoid' properties:
    --
    -- [/Associativity/]
    --   @f `'o'` (g `'o'` h) ≡ (f `'o'` g) `'o'` h@
    --
    -- /Note/: This property test is only available when this package is built with
    -- @base-4.9+@ or @transformers-0.5+@.
    semigroupoidLaws :: forall proxy s.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b))
    #else
      (Semigroupoid s, Eq2 s, Show2 s, Arbitrary2 s)
    #endif
      => proxy s -> Laws
    semigroupoidLaws :: forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Laws
    semigroupoidLaws proxy s
    p = String -> [(String, Property)] -> Laws
    Laws String
    "Semigroupoid"
      [ (String
    "Associativity", proxy s -> Property
    forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Property
    semigroupoidAssociativity proxy s
    p)
      ]

    -- | Tests everything from 'semigroupoidLaws' plus the following:
    --
    -- [/Commutative/]
    --   @f `'o'` g ≡ g `'o'` f@
    --
    -- /Note/: This property test is only available when this package is built with
    -- @base-4.9+@ or @transformers-0.5+@.
    commutativeSemigroupoidLaws :: forall proxy s.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b))
    #else
      (Semigroupoid s, Eq2 s, Show2 s, Arbitrary2 s)
    #endif
      => proxy s -> Laws
    commutativeSemigroupoidLaws :: forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Laws
    commutativeSemigroupoidLaws proxy s
    p = String -> [(String, Property)] -> Laws
    Laws String
    "Commutative Semigroupoid" ([(String, Property)] -> Laws) -> [(String, Property)] -> Laws
    forall a b. (a -> b) -> a -> b
    $ Laws -> [(String, Property)]
    lawsProperties (proxy s -> Laws
    forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Laws
    semigroupoidLaws proxy s
    p) [(String, Property)]
    -> [(String, Property)] -> [(String, Property)]
    forall a. [a] -> [a] -> [a]
    ++
      [ (String
    "Commutative", proxy s -> Property
    forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Property
    semigroupoidCommutativity proxy s
    p)
      ]

    semigroupoidAssociativity :: forall proxy s.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b))
    #else
      (Semigroupoid s, Eq2 s, Show2 s, Arbitrary2 s)
    #endif
      => proxy s -> Property
    semigroupoidAssociativity :: forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Property
    semigroupoidAssociativity proxy s
    _ = (Apply2 s Integer Integer
     -> Apply2 s Integer Integer -> Apply2 s Integer Integer -> Bool)
    -> Property
    forall prop. Testable prop => prop -> Property
    property ((Apply2 s Integer Integer
      -> Apply2 s Integer Integer -> Apply2 s Integer Integer -> Bool)
     -> Property)
    -> (Apply2 s Integer Integer
        -> Apply2 s Integer Integer -> Apply2 s Integer Integer -> Bool)
    -> Property
    forall a b. (a -> b) -> a -> b
    $ \(Apply2 (s Integer Integer
    f :: s Integer Integer)) (Apply2 (s Integer Integer
    g :: s Integer Integer)) (Apply2 (s Integer Integer
    h :: s Integer Integer)) -> s Integer Integer -> s Integer Integer -> Bool
    forall b (f :: * -> * -> *) a.
    (forall a1. (Eq a1, Eq b) => Eq (f a1 b), Eq a, Eq b) =>
    f a b -> f a b -> Bool
    eq2 (s Integer Integer
    f s Integer Integer -> s Integer Integer -> s Integer Integer
    forall j k1 i. s j k1 -> s i j -> s i k1
    forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
    Semigroupoid c =>
    c j k1 -> c i j -> c i k1
    `o` (s Integer Integer
    g s Integer Integer -> s Integer Integer -> s Integer Integer
    forall j k1 i. s j k1 -> s i j -> s i k1
    forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
    Semigroupoid c =>
    c j k1 -> c i j -> c i k1
    `o` s Integer Integer
    h)) ((s Integer Integer
    f s Integer Integer -> s Integer Integer -> s Integer Integer
    forall j k1 i. s j k1 -> s i j -> s i k1
    forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
    Semigroupoid c =>
    c j k1 -> c i j -> c i k1
    `o` s Integer Integer
    g) s Integer Integer -> s Integer Integer -> s Integer Integer
    forall j k1 i. s j k1 -> s i j -> s i k1
    forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
    Semigroupoid c =>
    c j k1 -> c i j -> c i k1
    `o` s Integer Integer
    h)

    semigroupoidCommutativity :: forall proxy s.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b))
    #else
      (Semigroupoid s, Eq2 s, Show2 s, Arbitrary2 s)
    #endif
      => proxy s -> Property
    semigroupoidCommutativity :: forall (proxy :: (* -> * -> *) -> *) (s :: * -> * -> *).
    (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b),
     forall a b. (Show a, Show b) => Show (s a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) =>
    proxy s -> Property
    semigroupoidCommutativity proxy s
    _ = (Apply2 s Integer Integer -> Apply2 s Integer Integer -> Bool)
    -> Property
    forall prop. Testable prop => prop -> Property
    property ((Apply2 s Integer Integer -> Apply2 s Integer Integer -> Bool)
     -> Property)
    -> (Apply2 s Integer Integer -> Apply2 s Integer Integer -> Bool)
    -> Property
    forall a b. (a -> b) -> a -> b
    $ \(Apply2 (s Integer Integer
    f :: s Integer Integer)) (Apply2 (s Integer Integer
    g :: s Integer Integer)) -> s Integer Integer -> s Integer Integer -> Bool
    forall b (f :: * -> * -> *) a.
    (forall a1. (Eq a1, Eq b) => Eq (f a1 b), Eq a, Eq b) =>
    f a b -> f a b -> Bool
    eq2 (s Integer Integer
    f s Integer Integer -> s Integer Integer -> s Integer Integer
    forall j k1 i. s j k1 -> s i j -> s i k1
    forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
    Semigroupoid c =>
    c j k1 -> c i j -> c i k1
    `o` s Integer Integer
    g) (s Integer Integer
    g s Integer Integer -> s Integer Integer -> s Integer Integer
    forall j k1 i. s j k1 -> s i j -> s i k1
    forall {k} (c :: k -> k -> *) (j :: k) (k1 :: k) (i :: k).
    Semigroupoid c =>
    c j k1 -> c i j -> c i k1
    `o` s Integer Integer
    f)

    #endif