{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}

-- | Monad properties
--
-- You will need @TypeApplications@ to use these.
module Test.Syd.Validity.Monad
    ( monadSpecOnValid
    , monadSpec
    , monadSpecOnArbitrary
    , monadSpecOnGens
    ) where

import Data.Data

import Control.Monad (ap)
import Data.Kind (Type)
import Data.GenValidity
import Test.QuickCheck.Gen (unGen)
import Test.QuickCheck.Random (mkQCGen)

import Test.Syd
import Test.QuickCheck

import Test.Syd.Validity.Functions
import Test.Syd.Validity.Utils

{-# ANN module "HLint: ignore Use fmap" #-}

{-# ANN module "HLint: ignore Use <$>" #-}

{-# ANN module "HLint: ignore Use >=>" #-}

{-# ANN module "HLint: ignore Use id" #-}

{-# ANN module "HLint: ignore Monad law, left identity" #-}

{-# ANN module "HLint: ignore Monad law, right identity" #-}

{-# ANN module "HLint: ignore Avoid lambda" #-}

{-# ANN module "HLint: ignore Reduce duplication" #-}

returnTypeStr ::
       forall (m :: Type -> Type). (Typeable m)
    => String
returnTypeStr :: String
returnTypeStr = [String] -> String
unwords [String
"return", String
"::", String
"a", String
"->", Typeable m => String
forall k (a :: k). Typeable a => String
nameOf @m, String
"a"]

bindTypeStr ::
       forall (m :: Type -> Type). (Typeable m)
    => String
bindTypeStr :: String
bindTypeStr =
    [String] -> String
unwords
        [ String
"(>>=)"
        , String
"::"
        , Typeable m => String
forall k (a :: k). Typeable a => String
nameOf @m
        , String
"a"
        , String
"->"
        , String
"(b"
        , String
"->"
        , Typeable m => String
forall k (a :: k). Typeable a => String
nameOf @m
        , String
"a)"
        , String
"->"
        , Typeable m => String
forall k (a :: k). Typeable a => String
nameOf @m
        , String
"b"
        ]

-- | Standard test spec for properties of Monad instances for values generated with GenValid instances
--
-- Example usage:
--
-- > monadSpecOnValid @[]
monadSpecOnValid ::
       forall (f :: Type -> Type).
       (Eq (f Int), Show (f Int), Monad f, Typeable f, GenValid (f Int))
    => Spec
monadSpecOnValid :: Spec
monadSpecOnValid = Gen (f Int) -> Spec
forall (f :: * -> *).
(Eq (f Int), Show (f Int), Monad f, Typeable f) =>
Gen (f Int) -> Spec
monadSpecWithInts @f Gen (f Int)
forall a. GenValid a => Gen a
genValid

-- | Standard test spec for properties of Monad instances for values generated with GenUnchecked instances
--
-- Example usage:
--
-- > monadSpec @[]
monadSpec ::
       forall (f :: Type -> Type).
       (Eq (f Int), Show (f Int), Monad f, Typeable f, GenUnchecked (f Int))
    => Spec
monadSpec :: Spec
monadSpec = Gen (f Int) -> Spec
forall (f :: * -> *).
(Eq (f Int), Show (f Int), Monad f, Typeable f) =>
Gen (f Int) -> Spec
monadSpecWithInts @f Gen (f Int)
forall a. GenUnchecked a => Gen a
genUnchecked

-- | Standard test spec for properties of Monad instances for values generated with Arbitrary instances
--
-- Example usage:
--
-- > monadSpecOnArbitrary @[]
monadSpecOnArbitrary ::
       forall (f :: Type -> Type).
       (Eq (f Int), Show (f Int), Monad f, Typeable f, Arbitrary (f Int))
    => Spec
monadSpecOnArbitrary :: Spec
monadSpecOnArbitrary = Gen (f Int) -> Spec
forall (f :: * -> *).
(Eq (f Int), Show (f Int), Monad f, Typeable f) =>
Gen (f Int) -> Spec
monadSpecWithInts @f Gen (f Int)
forall a. Arbitrary a => Gen a
arbitrary

monadSpecWithInts ::
       forall (f :: Type -> Type). (Eq (f Int), Show (f Int), Monad f, Typeable f)
    => Gen (f Int)
    -> Spec
monadSpecWithInts :: Gen (f Int) -> Spec
monadSpecWithInts Gen (f Int)
gen =
    Gen Int
-> String
-> Gen (f Int)
-> String
-> Gen (f Int)
-> String
-> Gen (Int -> Int)
-> String
-> Gen (Int -> f Int)
-> String
-> Gen (Int -> f Int)
-> String
-> Gen (f (Int -> Int))
-> String
-> Spec
forall (f :: * -> *) a b c.
(Show a, Show (f a), Show (f b), Show (f c), Eq (f a), Eq (f b),
 Eq (f c), Monad f, Typeable f, Typeable a, Typeable b,
 Typeable c) =>
Gen a
-> String
-> Gen (f a)
-> String
-> Gen (f b)
-> String
-> Gen (a -> b)
-> String
-> Gen (a -> f b)
-> String
-> Gen (b -> f c)
-> String
-> Gen (f (a -> b))
-> String
-> Spec
monadSpecOnGens
        @f
        @Int
        Gen Int
forall a. GenUnchecked a => Gen a
genUnchecked
        String
"int"
        Gen (f Int)
gen
        ([String] -> String
unwords [Typeable f => String
forall k (a :: k). Typeable a => String
nameOf @f, String
"of ints"])
        Gen (f Int)
gen
        ([String] -> String
unwords [Typeable f => String
forall k (a :: k). Typeable a => String
nameOf @f, String
"of ints"])
        (Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) (Int -> Int -> Int) -> Gen Int -> Gen (Int -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
forall a. GenUnchecked a => Gen a
genUnchecked)
        String
"increments"
        (do Int
s <- Gen Int
genListLength
            (Int -> f Int) -> Gen (Int -> f Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Int -> f Int) -> Gen (Int -> f Int))
-> (Int -> f Int) -> Gen (Int -> f Int)
forall a b. (a -> b) -> a -> b
$ \Int
b -> Gen (f Int) -> QCGen -> Int -> f Int
forall a. Gen a -> QCGen -> Int -> a
unGen Gen (f Int)
gen (Int -> QCGen
mkQCGen Int
b) Int
s)
        String
"perturbations using the int"
        (do Int
s <- Gen Int
genListLength
            (Int -> f Int) -> Gen (Int -> f Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Int -> f Int) -> Gen (Int -> f Int))
-> (Int -> f Int) -> Gen (Int -> f Int)
forall a b. (a -> b) -> a -> b
$ \Int
b -> Gen (f Int) -> QCGen -> Int -> f Int
forall a. Gen a -> QCGen -> Int -> a
unGen Gen (f Int)
gen (Int -> QCGen
mkQCGen (Int -> QCGen) -> Int -> QCGen
forall a b. (a -> b) -> a -> b
$ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
b) Int
s)
        String
"perturbations using the double the int"
        ((Int -> Int) -> f (Int -> Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Int -> Int) -> f (Int -> Int))
-> Gen (Int -> Int) -> Gen (f (Int -> Int))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) (Int -> Int -> Int) -> Gen Int -> Gen (Int -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
forall a. GenUnchecked a => Gen a
genUnchecked))
        ([String] -> String
unwords [Typeable f => String
forall k (a :: k). Typeable a => String
nameOf @f, String
"of additions"])

-- | Standard test spec for properties of Monad instances for values generated by given generators (and names for those generator).
--
-- Example usage:
--
-- > monadSpecOnGens
-- >     @[]
-- >     @Int
-- >     (pure 4)
-- >     "four"
-- >     (genListOf $ pure 5)
-- >     "list of fives"
-- >     (genListOf $ pure 6)
-- >     "list of sixes"
-- >     ((*) <$> genValid)
-- >     "factorisations"
-- >     (pure $ \a -> [a])
-- >     "singletonisation"
-- >     (pure $ \a -> [a])
-- >     "singletonisation"
-- >     (pure $ pure (+ 1))
-- >     "increment in list"
monadSpecOnGens ::
       forall (f :: Type -> Type) (a :: Type) (b :: Type) (c :: Type).
       ( Show a
       , Show (f a)
       , Show (f b)
       , Show (f c)
       , Eq (f a)
       , Eq (f b)
       , Eq (f c)
       , Monad f
       , Typeable f
       , Typeable a
       , Typeable b
       , Typeable c
       )
    => Gen a
    -> String
    -> Gen (f a)
    -> String
    -> Gen (f b)
    -> String
    -> Gen (a -> b)
    -> String
    -> Gen (a -> f b)
    -> String
    -> Gen (b -> f c)
    -> String
    -> Gen (f (a -> b))
    -> String
    -> Spec
monadSpecOnGens :: Gen a
-> String
-> Gen (f a)
-> String
-> Gen (f b)
-> String
-> Gen (a -> b)
-> String
-> Gen (a -> f b)
-> String
-> Gen (b -> f c)
-> String
-> Gen (f (a -> b))
-> String
-> Spec
monadSpecOnGens Gen a
gena String
genaname Gen (f a)
gen String
genname Gen (f b)
genb String
genbname Gen (a -> b)
geng String
gengname Gen (a -> f b)
genbf String
genbfname Gen (b -> f c)
gencf String
gencfname Gen (f (a -> b))
genfab String
genfabname =
    Spec -> Spec
forall (a :: [*]) b c. TestDefM a b c -> TestDefM a b c
parallel (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$
    String -> Spec -> Spec
forall (outers :: [*]) inner.
String -> TestDefM outers inner () -> TestDefM outers inner ()
describe (String
"Monad " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Typeable f => String
forall k (a :: k). Typeable a => String
nameOf @f) (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
        String -> Spec -> Spec
forall (outers :: [*]) inner.
String -> TestDefM outers inner () -> TestDefM outers inner ()
describe ([String] -> String
unwords [Typeable f => String
forall (m :: * -> *). Typeable m => String
returnTypeStr @f, String
"and", Typeable f => String
forall (m :: * -> *). Typeable m => String
bindTypeStr @f]) (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [ String
"satisfy the first Monad law: 'return a >>= k = k a' for"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @a String
genaname
                     , String
"and"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(a -> f b) String
genbfname
                     ]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
                (a -> Anon (a -> f b) -> f b)
-> (a -> Anon (a -> f b) -> f b)
-> Gen (a, Anon (a -> f b))
-> ((a, Anon (a -> f b)) -> [(a, Anon (a -> f b))])
-> 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 (Anon a -> f b
k) -> a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a f a -> (a -> f b) -> f b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> f b
k)
                    (\a
a (Anon a -> f b
k) -> a -> f b
k a
a)
                    ((,) (a -> Anon (a -> f b) -> (a, Anon (a -> f b)))
-> Gen a -> Gen (Anon (a -> f b) -> (a, Anon (a -> f b)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
gena Gen (Anon (a -> f b) -> (a, Anon (a -> f b)))
-> Gen (Anon (a -> f b)) -> Gen (a, Anon (a -> f b))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((a -> f b) -> Anon (a -> f b)
forall a. a -> Anon a
Anon ((a -> f b) -> Anon (a -> f b))
-> Gen (a -> f b) -> Gen (Anon (a -> f b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (a -> f b)
genbf))
                    (a, Anon (a -> f b)) -> [(a, Anon (a -> f b))]
forall a. a -> [a]
shrinkNothing
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [ String
"satisfy the second Monad law: 'm >>= return = m' for"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f a) String
genname
                     ]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
                (f a -> f a)
-> (f a -> f a) -> Gen (f a) -> (f a -> [f a]) -> Property
forall a b.
(Show a, Show b, Eq b) =>
(a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
equivalentOnGen (\f a
m -> f a
m f a -> (a -> f a) -> f a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return) (\f a
m -> f a
m) Gen (f a)
gen f a -> [f a]
forall a. a -> [a]
shrinkNothing
        String -> Spec -> Spec
forall (outers :: [*]) inner.
String -> TestDefM outers inner () -> TestDefM outers inner ()
describe (Typeable f => String
forall (m :: * -> *). Typeable m => String
bindTypeStr @f) (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [ String
"satisfies the third Monad law: 'm >>= (x -> k x >>= h) = (m >>= k) >>= h' for"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f a) String
genname
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(a -> f b) String
genbfname
                     , String
"and"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(b -> f c) String
gencfname
                     ]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
            (f a -> Anon (a -> f b) -> Anon (b -> f c) -> f c)
-> (f a -> Anon (a -> f b) -> Anon (b -> f c) -> f c)
-> Gen (f a, Anon (a -> f b), Anon (b -> f c))
-> ((f a, Anon (a -> f b), Anon (b -> f c))
    -> [(f a, Anon (a -> f b), Anon (b -> f c))])
-> Property
forall a b c d.
(Show a, Show b, Show c, Show d, Eq d) =>
(a -> b -> c -> d)
-> (a -> b -> c -> d)
-> Gen (a, b, c)
-> ((a, b, c) -> [(a, b, c)])
-> Property
equivalentOnGens3
                (\f a
m (Anon a -> f b
k) (Anon b -> f c
h) -> f a
m f a -> (a -> f c) -> f c
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\a
x -> a -> f b
k a
x f b -> (b -> f c) -> f c
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= b -> f c
h))
                (\f a
m (Anon a -> f b
k) (Anon b -> f c
h) -> (f a
m f a -> (a -> f b) -> f b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> f b
k) f b -> (b -> f c) -> f c
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= b -> f c
h)
                ((,,) (f a
 -> Anon (a -> f b)
 -> Anon (b -> f c)
 -> (f a, Anon (a -> f b), Anon (b -> f c)))
-> Gen (f a)
-> Gen
     (Anon (a -> f b)
      -> Anon (b -> f c) -> (f a, Anon (a -> f b), Anon (b -> f c)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (f a)
gen Gen
  (Anon (a -> f b)
   -> Anon (b -> f c) -> (f a, Anon (a -> f b), Anon (b -> f c)))
-> Gen (Anon (a -> f b))
-> Gen (Anon (b -> f c) -> (f a, Anon (a -> f b), Anon (b -> f c)))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((a -> f b) -> Anon (a -> f b)
forall a. a -> Anon a
Anon ((a -> f b) -> Anon (a -> f b))
-> Gen (a -> f b) -> Gen (Anon (a -> f b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (a -> f b)
genbf) Gen (Anon (b -> f c) -> (f a, Anon (a -> f b), Anon (b -> f c)))
-> Gen (Anon (b -> f c))
-> Gen (f a, Anon (a -> f b), Anon (b -> f c))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((b -> f c) -> Anon (b -> f c)
forall a. a -> Anon a
Anon ((b -> f c) -> Anon (b -> f c))
-> Gen (b -> f c) -> Gen (Anon (b -> f c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (b -> f c)
gencf))
                (f a, Anon (a -> f b), Anon (b -> f c))
-> [(f a, Anon (a -> f b), Anon (b -> f c))]
forall a. a -> [a]
shrinkNothing
        String -> Spec -> Spec
forall (outers :: [*]) inner.
String -> TestDefM outers inner () -> TestDefM outers inner ()
describe ([String] -> String
unwords [String
"relation with Applicative", Typeable f => String
forall k (a :: k). Typeable a => String
nameOf @f]) (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [String
"satisfies 'pure = return' for", String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f a) String
genname]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
                (a -> f a) -> (a -> f a) -> Gen a -> (a -> [a]) -> Property
forall a b.
(Show a, Show b, Eq b) =>
(a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
equivalentOnGen (forall a. Applicative f => a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure @f) (forall a. Monad f => a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return @f) Gen a
gena a -> [a]
forall a. a -> [a]
shrinkNothing
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [ String
"satisfies '(<*>) = ap' for"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f (a -> b)) String
genfabname
                     , String
"and"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f a) String
genname
                     ]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
                (Anon (f (a -> b)) -> f a -> f b)
-> (Anon (f (a -> b)) -> f a -> f b)
-> Gen (Anon (f (a -> b)), f a)
-> ((Anon (f (a -> b)), f a) -> [(Anon (f (a -> b)), f 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
                    (\(Anon f (a -> b)
a) f a
b -> f (a -> b)
a f (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f a
b)
                    (\(Anon f (a -> b)
a) f a
b -> f (a -> b) -> f a -> f b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap f (a -> b)
a f a
b)
                    ((,) (Anon (f (a -> b)) -> f a -> (Anon (f (a -> b)), f a))
-> Gen (Anon (f (a -> b))) -> Gen (f a -> (Anon (f (a -> b)), f a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (f (a -> b) -> Anon (f (a -> b))
forall a. a -> Anon a
Anon (f (a -> b) -> Anon (f (a -> b)))
-> Gen (f (a -> b)) -> Gen (Anon (f (a -> b)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (f (a -> b))
genfab) Gen (f a -> (Anon (f (a -> b)), f a))
-> Gen (f a) -> Gen (Anon (f (a -> b)), f a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (f a)
gen)
                    (Anon (f (a -> b)), f a) -> [(Anon (f (a -> b)), f a)]
forall a. a -> [a]
shrinkNothing
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [ String
"satisfies '(>>) = (*>)' for"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f a) String
genname
                     , String
"and"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f b) String
genbname
                     ]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
                (f a -> f b -> f b)
-> (f a -> f b -> f b)
-> Gen (f a, f b)
-> ((f a, f b) -> [(f a, f b)])
-> 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 f a -> f b -> f b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>) f a -> f b -> f b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
(*>) ((,) (f a -> f b -> (f a, f b)) -> Gen (f a) -> Gen (f b -> (f a, f b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (f a)
gen Gen (f b -> (f a, f b)) -> Gen (f b) -> Gen (f a, f b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (f b)
genb) (f a, f b) -> [(f a, f b)]
forall a. a -> [a]
shrinkNothing
        String -> Spec -> Spec
forall (outers :: [*]) inner.
String -> TestDefM outers inner () -> TestDefM outers inner ()
describe ([String] -> String
unwords [String
"relation with Functor", Typeable f => String
forall k (a :: k). Typeable a => String
nameOf @f]) (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$
            String -> Property -> Spec
forall (outers :: [*]) inner test.
(HasCallStack, IsTest test, Arg1 test ~ (), Arg2 test ~ inner) =>
String -> test -> TestDefM outers inner ()
it
                ([String] -> String
unwords
                     [ String
"satisfies 'fmap f xs = xs >>= return . f' for"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(a -> b) String
gengname
                     , String
"and"
                     , String -> String
forall k (a :: k). Typeable a => String -> String
genDescr @(f a) String
genname
                     ]) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
            (Anon (a -> b) -> f a -> f b)
-> (Anon (a -> b) -> f a -> f b)
-> Gen (Anon (a -> b), f a)
-> ((Anon (a -> b), f a) -> [(Anon (a -> b), f 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
                (\(Anon a -> b
f) f a
xs -> (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f f a
xs)
                (\(Anon a -> b
f) f a
xs -> f a
xs f a -> (a -> f b) -> f b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (b -> f b
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> f b) -> (a -> b) -> a -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f))
                ((,) (Anon (a -> b) -> f a -> (Anon (a -> b), f a))
-> Gen (Anon (a -> b)) -> Gen (f a -> (Anon (a -> b), f a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((a -> b) -> Anon (a -> b)
forall a. a -> Anon a
Anon ((a -> b) -> Anon (a -> b)) -> Gen (a -> b) -> Gen (Anon (a -> b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (a -> b)
geng) Gen (f a -> (Anon (a -> b), f a))
-> Gen (f a) -> Gen (Anon (a -> b), f a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (f a)
gen)
                (Anon (a -> b), f a) -> [(Anon (a -> b), f a)]
forall a. a -> [a]
shrinkNothing