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

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

{-# OPTIONS_GHC -Wall #-}

module Test.QuickCheck.Classes.Bitraversable
  (
#if HAVE_BINARY_LAWS
    bitraversableLaws
#endif
  ) where

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

import Test.QuickCheck.Classes.Internal

#if HAVE_BINARY_LAWS

-- | Tests the following 'Bitraversable' properties:
--
-- [/Naturality/]
--   @'bitraverse' (t '.' f) (t '.' g) ≡ t '.' 'bitraverse' f g@ for every applicative transformation @t@
-- [/Identity/]
--   @'bitraverse' 'Identity' 'Identity' ≡ 'Identity'@
-- [/Composition/] 
--   @'Compose' '.' 'fmap' ('bitraverse' g1 g2) '.' 'bitraverse' f1 f2 ≡ 'bitraverse' ('Compose' '.' 'fmap' g1 g2 '.' f1) ('Compose' '.' 'fmap' g2 '.' f2)@
--
-- /Note/: This property test is only available when this package is built with
-- @base-4.9+@ or @transformers-0.5+@.
bitraversableLaws :: forall proxy f.
#if HAVE_QUANTIFIED_CONSTRAINTS
  (Bitraversable 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
  (Bitraversable f, Eq2 f, Show2 f, Arbitrary2 f)
#endif
  => proxy f -> Laws
bitraversableLaws :: proxy f -> Laws
bitraversableLaws proxy f
p = String -> [(String, Property)] -> Laws
Laws String
"Bitraversable"
  [ (String
"Naturality", proxy f -> Property
forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
(Bitraversable 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
bitraversableNaturality proxy f
p)
  , (String
"Identity", proxy f -> Property
forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
(Bitraversable 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
bitraversableIdentity proxy f
p)
  , (String
"Composition", proxy f -> Property
forall (proxy :: (* -> * -> *) -> *) (f :: * -> * -> *).
(Bitraversable 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
bitraversableComposition proxy f
p)
  ]

bitraversableNaturality :: forall proxy f.
#if HAVE_QUANTIFIED_CONSTRAINTS
  (Bitraversable 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
  (Bitraversable f, Eq2 f, Show2 f, Arbitrary2 f)
#endif
  => proxy f -> Property
bitraversableNaturality :: proxy f -> Property
bitraversableNaturality 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)) ->
  let t :: Compose Triple (Writer (Set Integer)) a
-> Compose (Writer (Set Integer)) Triple a
t = Compose Triple (Writer (Set Integer)) a
-> Compose (Writer (Set Integer)) Triple a
forall a.
Compose Triple (Writer (Set Integer)) a
-> Compose (Writer (Set Integer)) Triple a
apTrans
      f :: Integer -> Compose Triple (Writer (Set Integer)) Integer
f = Integer -> Compose Triple (Writer (Set Integer)) Integer
func4
      g :: Integer -> Compose Triple (Writer (Set Integer)) Integer
g = Integer -> Compose Triple (Writer (Set Integer)) Integer
func4
      x' :: Compose (Writer (Set Integer)) Triple (f Integer Integer)
x' = (Integer -> Compose (Writer (Set Integer)) Triple Integer)
-> (Integer -> Compose (Writer (Set Integer)) Triple Integer)
-> f Integer Integer
-> Compose (Writer (Set Integer)) Triple (f Integer Integer)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse (Compose Triple (Writer (Set Integer)) Integer
-> Compose (Writer (Set Integer)) Triple Integer
forall a.
Compose Triple (Writer (Set Integer)) a
-> Compose (Writer (Set Integer)) Triple a
t (Compose Triple (Writer (Set Integer)) Integer
 -> Compose (Writer (Set Integer)) Triple Integer)
-> (Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> Integer
-> Compose (Writer (Set Integer)) Triple Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Compose Triple (Writer (Set Integer)) Integer
f) (Compose Triple (Writer (Set Integer)) Integer
-> Compose (Writer (Set Integer)) Triple Integer
forall a.
Compose Triple (Writer (Set Integer)) a
-> Compose (Writer (Set Integer)) Triple a
t (Compose Triple (Writer (Set Integer)) Integer
 -> Compose (Writer (Set Integer)) Triple Integer)
-> (Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> Integer
-> Compose (Writer (Set Integer)) Triple Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Compose Triple (Writer (Set Integer)) Integer
g) f Integer Integer
x
      y' :: Compose (Writer (Set Integer)) Triple (f Integer Integer)
y' = Compose Triple (Writer (Set Integer)) (f Integer Integer)
-> Compose (Writer (Set Integer)) Triple (f Integer Integer)
forall a.
Compose Triple (Writer (Set Integer)) a
-> Compose (Writer (Set Integer)) Triple a
t ((Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> (Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> f Integer Integer
-> Compose Triple (Writer (Set Integer)) (f Integer Integer)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse Integer -> Compose Triple (Writer (Set Integer)) Integer
f Integer -> Compose Triple (Writer (Set Integer)) Integer
g f Integer Integer
x)
  in Compose (Writer (Set Integer)) Triple (f Integer Integer)
-> Compose (Writer (Set Integer)) Triple (f Integer Integer)
-> Bool
forall (f :: * -> *) (g :: * -> * -> *) x y.
(forall a. Eq a => Eq (f a),
 forall a b. (Eq a, Eq b) => Eq (g a b), Eq x, Eq y) =>
f (g x y) -> f (g x y) -> Bool
eq1_2 Compose (Writer (Set Integer)) Triple (f Integer Integer)
x' Compose (Writer (Set Integer)) Triple (f Integer Integer)
y'

bitraversableIdentity :: forall proxy f.
#if HAVE_QUANTIFIED_CONSTRAINTS
  (Bitraversable 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
  (Bitraversable f, Eq2 f, Show2 f, Arbitrary2 f)
#endif
  => proxy f -> Property
bitraversableIdentity :: proxy f -> Property
bitraversableIdentity 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)) -> Identity (f Integer Integer)
-> Identity (f Integer Integer) -> Bool
forall (f :: * -> *) (g :: * -> * -> *) x y.
(forall a. Eq a => Eq (f a),
 forall a b. (Eq a, Eq b) => Eq (g a b), Eq x, Eq y) =>
f (g x y) -> f (g x y) -> Bool
eq1_2 ((Integer -> Identity Integer)
-> (Integer -> Identity Integer)
-> f Integer Integer
-> Identity (f Integer Integer)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse Integer -> Identity Integer
forall a. a -> Identity a
Identity Integer -> Identity Integer
forall a. a -> Identity a
Identity f Integer Integer
x) (f Integer Integer -> Identity (f Integer Integer)
forall a. a -> Identity a
Identity f Integer Integer
x)

bitraversableComposition :: forall proxy f.
#if HAVE_QUANTIFIED_CONSTRAINTS
  (Bitraversable 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
  (Bitraversable f, Eq2 f, Show2 f, Arbitrary2 f)
#endif
  => proxy f -> Property
bitraversableComposition :: proxy f -> Property
bitraversableComposition 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)) ->
  let f1 :: Integer -> Triple Integer
f1 = Integer -> Triple Integer
func6
      f2 :: Integer -> Triple Integer
f2 = Integer -> Triple Integer
func5
      g1 :: Integer -> Compose Triple (Writer (Set Integer)) Integer
g1 = Integer -> Compose Triple (Writer (Set Integer)) Integer
func4
      g2 :: Integer -> Compose Triple (Writer (Set Integer)) Integer
g2 = Integer -> Compose Triple (Writer (Set Integer)) Integer
func4
      x' :: Compose
  Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
x' = Triple (Compose Triple (Writer (Set Integer)) (f Integer Integer))
-> Compose
     Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (Triple (Compose Triple (Writer (Set Integer)) (f Integer Integer))
 -> Compose
      Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer))
-> (f Integer Integer
    -> Triple
         (Compose Triple (Writer (Set Integer)) (f Integer Integer)))
-> f Integer Integer
-> Compose
     Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (f Integer Integer
 -> Compose Triple (Writer (Set Integer)) (f Integer Integer))
-> Triple (f Integer Integer)
-> Triple
     (Compose Triple (Writer (Set Integer)) (f Integer Integer))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> (Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> f Integer Integer
-> Compose Triple (Writer (Set Integer)) (f Integer Integer)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse Integer -> Compose Triple (Writer (Set Integer)) Integer
g1 Integer -> Compose Triple (Writer (Set Integer)) Integer
g2) (Triple (f Integer Integer)
 -> Triple
      (Compose Triple (Writer (Set Integer)) (f Integer Integer)))
-> (f Integer Integer -> Triple (f Integer Integer))
-> f Integer Integer
-> Triple
     (Compose Triple (Writer (Set Integer)) (f Integer Integer))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Triple Integer)
-> (Integer -> Triple Integer)
-> f Integer Integer
-> Triple (f Integer Integer)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse Integer -> Triple Integer
f1 Integer -> Triple Integer
f2 (f Integer Integer
 -> Compose
      Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer))
-> f Integer Integer
-> Compose
     Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
forall a b. (a -> b) -> a -> b
$ f Integer Integer
x
      y' :: Compose
  Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
y' = (Integer
 -> Compose Triple (Compose Triple (Writer (Set Integer))) Integer)
-> (Integer
    -> Compose Triple (Compose Triple (Writer (Set Integer))) Integer)
-> f Integer Integer
-> Compose
     Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse (Triple (Compose Triple (Writer (Set Integer)) Integer)
-> Compose Triple (Compose Triple (Writer (Set Integer))) Integer
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (Triple (Compose Triple (Writer (Set Integer)) Integer)
 -> Compose Triple (Compose Triple (Writer (Set Integer))) Integer)
-> (Integer
    -> Triple (Compose Triple (Writer (Set Integer)) Integer))
-> Integer
-> Compose Triple (Compose Triple (Writer (Set Integer))) Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> Triple Integer
-> Triple (Compose Triple (Writer (Set Integer)) Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Compose Triple (Writer (Set Integer)) Integer
g1 (Triple Integer
 -> Triple (Compose Triple (Writer (Set Integer)) Integer))
-> (Integer -> Triple Integer)
-> Integer
-> Triple (Compose Triple (Writer (Set Integer)) Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Triple Integer
f1) (Triple (Compose Triple (Writer (Set Integer)) Integer)
-> Compose Triple (Compose Triple (Writer (Set Integer))) Integer
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (Triple (Compose Triple (Writer (Set Integer)) Integer)
 -> Compose Triple (Compose Triple (Writer (Set Integer))) Integer)
-> (Integer
    -> Triple (Compose Triple (Writer (Set Integer)) Integer))
-> Integer
-> Compose Triple (Compose Triple (Writer (Set Integer))) Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Compose Triple (Writer (Set Integer)) Integer)
-> Triple Integer
-> Triple (Compose Triple (Writer (Set Integer)) Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Compose Triple (Writer (Set Integer)) Integer
g2 (Triple Integer
 -> Triple (Compose Triple (Writer (Set Integer)) Integer))
-> (Integer -> Triple Integer)
-> Integer
-> Triple (Compose Triple (Writer (Set Integer)) Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Triple Integer
f2) f Integer Integer
x
  in Compose
  Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
-> Compose
     Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
-> Bool
forall (f :: * -> *) (g :: * -> * -> *) x y.
(forall a. Eq a => Eq (f a),
 forall a b. (Eq a, Eq b) => Eq (g a b), Eq x, Eq y) =>
f (g x y) -> f (g x y) -> Bool
eq1_2 Compose
  Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
x' Compose
  Triple (Compose Triple (Writer (Set Integer))) (f Integer Integer)
y'

#endif