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

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

    {-# OPTIONS_GHC -Wall #-}

    module Test.QuickCheck.Classes.Bifunctor
      (
    #if HAVE_BINARY_LAWS
        bifunctorLaws
    #endif
      ) where

    import Data.Bifunctor(Bifunctor(..))
    import Test.QuickCheck hiding ((.&.))
    #if HAVE_BINARY_LAWS
    import Data.Functor.Classes (Eq2,Show2)
    #endif
    import Test.QuickCheck.Property (Property)

    import Test.QuickCheck.Classes.Internal

    #if HAVE_BINARY_LAWS

    -- | Tests the following 'Bifunctor' properties:
    --
    -- [/Identity/]
    --   @'bimap' 'id' 'id' ≡ 'id'@
    -- [/First Identity/]
    --   @'first' 'id' ≡ 'id'@
    -- [/Second Identity/]
    --   @'second' 'id' ≡ 'id'@
    -- [/Bifunctor Composition/]
    --   @'bimap' f g ≡ 'first' f '.' 'second' g@
    --
    -- /Note/: This property test is only available when this package is built with
    -- @base-4.9+@ or @transformers-0.5+@.
    bifunctorLaws :: forall proxy f.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b))
    #else
      (Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f)
    #endif
      => proxy f -> Laws
    bifunctorLaws :: forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Laws
    bifunctorLaws proxy f
    p = String -> [(String, Property)] -> Laws
    Laws String
    "Bifunctor"
      [ (String
    "Identity", proxy f -> Property
    forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorIdentity proxy f
    p)
      , (String
    "First Identity", proxy f -> Property
    forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorFirstIdentity proxy f
    p)
      , (String
    "Second Identity", proxy f -> Property
    forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorSecondIdentity proxy f
    p)
      , (String
    "Bifunctor Composition", proxy f -> Property
    forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorComposition proxy f
    p)
      ]

    bifunctorIdentity :: forall proxy f.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b))
    #else
      (Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f)
    #endif
      => proxy f -> Property
    bifunctorIdentity :: forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorIdentity proxy f
    _ = (Apply2 f Integer Integer -> Bool) -> Property
    forall prop. Testable prop => prop -> Property
    property ((Apply2 f Integer Integer -> Bool) -> Property)
    -> (Apply2 f Integer Integer -> Bool) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(Apply2 (f Integer Integer
    x :: f Integer Integer)) -> f Integer Integer -> f 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 ((Integer -> Integer)
    -> (Integer -> Integer) -> f Integer Integer -> f Integer Integer
    forall a b c d. (a -> b) -> (c -> d) -> f a c -> f b d
    forall (p :: * -> * -> *) a b c d.
    Bifunctor p =>
    (a -> b) -> (c -> d) -> p a c -> p b d
    bimap Integer -> Integer
    forall a. a -> a
    id Integer -> Integer
    forall a. a -> a
    id f Integer Integer
    x) f Integer Integer
    x

    bifunctorFirstIdentity :: forall proxy f.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b))
    #else
      (Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f)
    #endif
      => proxy f -> Property
    bifunctorFirstIdentity :: forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorFirstIdentity proxy f
    _ = (Apply2 f Integer Integer -> Bool) -> Property
    forall prop. Testable prop => prop -> Property
    property ((Apply2 f Integer Integer -> Bool) -> Property)
    -> (Apply2 f Integer Integer -> Bool) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(Apply2 (f Integer Integer
    x :: f Integer Integer)) -> f Integer Integer -> f 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 ((Integer -> Integer) -> f Integer Integer -> f Integer Integer
    forall a b c. (a -> b) -> f a c -> f b c
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first Integer -> Integer
    forall a. a -> a
    id f Integer Integer
    x) f Integer Integer
    x

    bifunctorSecondIdentity :: forall proxy f.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b))
    #else
      (Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f)
    #endif
      => proxy f -> Property
    bifunctorSecondIdentity :: forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorSecondIdentity proxy f
    _ = (Apply2 f Integer Integer -> Bool) -> Property
    forall prop. Testable prop => prop -> Property
    property ((Apply2 f Integer Integer -> Bool) -> Property)
    -> (Apply2 f Integer Integer -> Bool) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(Apply2 (f Integer Integer
    x :: f Integer Integer)) -> f Integer Integer -> f 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 ((Integer -> Integer) -> f Integer Integer -> f Integer Integer
    forall b c a. (b -> c) -> f a b -> f a c
    forall (p :: * -> * -> *) b c a.
    Bifunctor p =>
    (b -> c) -> p a b -> p a c
    second Integer -> Integer
    forall a. a -> a
    id f Integer Integer
    x) f Integer Integer
    x

    bifunctorComposition :: forall proxy f.
    #if HAVE_QUANTIFIED_CONSTRAINTS
      (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b))
    #else
      (Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f)
    #endif
      => proxy f -> Property
    bifunctorComposition :: forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
    (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b),
     forall a b. (Show a, Show b) => Show (f a b),
     forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) =>
    proxy f -> Property
    bifunctorComposition proxy f
    _ = (Apply2 f Integer Integer -> Bool) -> Property
    forall prop. Testable prop => prop -> Property
    property ((Apply2 f Integer Integer -> Bool) -> Property)
    -> (Apply2 f Integer Integer -> Bool) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(Apply2 (f Integer Integer
    z :: f Integer Integer)) -> f Integer Integer -> f 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 ((Integer -> Integer)
    -> (Integer -> Integer) -> f Integer Integer -> f Integer Integer
    forall a b c d. (a -> b) -> (c -> d) -> f a c -> f b d
    forall (p :: * -> * -> *) a b c d.
    Bifunctor p =>
    (a -> b) -> (c -> d) -> p a c -> p b d
    bimap Integer -> Integer
    forall a. a -> a
    id Integer -> Integer
    forall a. a -> a
    id f Integer Integer
    z) (((Integer -> Integer) -> f Integer Integer -> f Integer Integer
    forall a b c. (a -> b) -> f a c -> f b c
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first Integer -> Integer
    forall a. a -> a
    id (f Integer Integer -> f Integer Integer)
    -> (f Integer Integer -> f Integer Integer)
    -> f Integer Integer
    -> f Integer Integer
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Integer -> Integer) -> f Integer Integer -> f Integer Integer
    forall b c a. (b -> c) -> f a b -> f a c
    forall (p :: * -> * -> *) b c a.
    Bifunctor p =>
    (b -> c) -> p a b -> p a c
    second Integer -> Integer
    forall a. a -> a
    id) f Integer Integer
    z)

    #endif