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

    module Test.Validity.Functions.Equivalence
      ( equivalentOnGen,
        equivalent,
        equivalentOnArbitrary,
        equivalentOnGens2,
        equivalent2,
        equivalentOnArbitrary2,
        equivalentWhenFirstSucceedsOnGen,
        equivalentWhenFirstSucceeds,
        equivalentWhenFirstSucceedsOnArbitrary,
        equivalentWhenFirstSucceedsOnGens2,
        equivalentWhenFirstSucceeds2,
        equivalentWhenFirstSucceedsOnArbitrary2,
        equivalentWhenSecondSucceedsOnGen,
        equivalentWhenSecondSucceeds,
        equivalentWhenSecondSucceedsOnArbitrary,
        equivalentWhenSecondSucceedsOnGens2,
        equivalentWhenSecondSucceeds2,
        equivalentWhenSecondSucceedsOnArbitrary2,
        equivalentWhenSucceedOnGen,
        equivalentWhenSucceed,
        equivalentWhenSucceedOnArbitrary,
        equivalentWhenSucceedOnGens2,
        equivalentWhenSucceed2,
        equivalentWhenSucceedOnArbitrary2,
        equivalentOnGens3,
        equivalent3,
        equivalentOnArbitrary3,
      )
    where

    import Data.GenValidity
    import Test.Hspec
    import Test.QuickCheck
    import Test.Validity.Types

    equivalentOnGen ::
      (Show a, Show b, Eq b) =>
      (a -> b) ->
      (a -> b) ->
      Gen a ->
      (a -> [a]) ->
      Property
    equivalentOnGen :: forall a b.
    (Show a, Show b, Eq b) =>
    (a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    equivalentOnGen a -> b
    f a -> b
    g Gen a
    gen a -> [a]
    s = Gen a -> (a -> [a]) -> (a -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen a
    gen a -> [a]
    s ((a -> Expectation) -> Property) -> (a -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \a
    a -> a -> b
    f a
    a b -> b -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b
    g a
    a

    equivalent ::
      (Show a, GenValid a, Show b, Eq b) =>
      (a -> b) ->
      (a -> b) ->
      Property
    equivalent :: forall a b.
    (Show a, GenValid a, Show b, Eq b) =>
    (a -> b) -> (a -> b) -> Property
    equivalent a -> b
    f a -> b
    g = (a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    forall a b.
    (Show a, Show b, Eq b) =>
    (a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    equivalentOnGen a -> b
    f a -> b
    g Gen a
    forall a. GenValid a => Gen a
    genValid a -> [a]
    forall a. GenValid a => a -> [a]
    shrinkValid

    -- |
    --
    -- prop> equivalentOnArbitrary ((* 2) . (+ 1)) ((+ 2) . (* 2) :: Int -> Int)
    equivalentOnArbitrary ::
      (Show a, Arbitrary a, Show b, Eq b) =>
      (a -> b) ->
      (a -> b) ->
      Property
    equivalentOnArbitrary :: forall a b.
    (Show a, Arbitrary a, Show b, Eq b) =>
    (a -> b) -> (a -> b) -> Property
    equivalentOnArbitrary a -> b
    f a -> b
    g = (a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    forall a b.
    (Show a, Show b, Eq b) =>
    (a -> b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    equivalentOnGen a -> b
    f a -> b
    g Gen a
    forall a. Arbitrary a => Gen a
    arbitrary a -> [a]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentOnGens2 ::
      (Show a, Show b, Show c, Eq c) =>
      (a -> b -> c) ->
      (a -> b -> c) ->
      Gen (a, b) ->
      ((a, b) -> [(a, b)]) ->
      Property
    equivalentOnGens2 :: 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 -> b -> c
    f a -> b -> c
    g Gen (a, b)
    gen (a, b) -> [(a, b)]
    s =
      Gen (a, b)
    -> ((a, b) -> [(a, b)]) -> ((a, b) -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen (a, b)
    gen (a, b) -> [(a, b)]
    s (((a, b) -> Expectation) -> Property)
    -> ((a, b) -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, b
    b) -> a -> b -> c
    f a
    a b
    b c -> c -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b -> c
    g a
    a b
    b

    equivalent2 ::
      (Show a, GenValid a, Show b, GenValid b, Show c, Eq c) =>
      (a -> b -> c) ->
      (a -> b -> c) ->
      Property
    equivalent2 :: forall a b c.
    (Show a, GenValid a, Show b, GenValid b, Show c, Eq c) =>
    (a -> b -> c) -> (a -> b -> c) -> Property
    equivalent2 a -> b -> c
    f a -> b -> c
    g = (a -> b -> c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, 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 -> b -> c
    f a -> b -> c
    g Gen (a, b)
    forall a. GenValid a => Gen a
    genValid (a, b) -> [(a, b)]
    forall a. GenValid a => a -> [a]
    shrinkValid

    -- |
    --
    -- prop> equivalentOnArbitrary2 (+) ((+) :: Int -> Int -> Int)
    equivalentOnArbitrary2 ::
      (Show a, Arbitrary a, Show b, Arbitrary b, Show c, Eq c) =>
      (a -> b -> c) ->
      (a -> b -> c) ->
      Property
    equivalentOnArbitrary2 :: forall a b c.
    (Show a, Arbitrary a, Show b, Arbitrary b, Show c, Eq c) =>
    (a -> b -> c) -> (a -> b -> c) -> Property
    equivalentOnArbitrary2 a -> b -> c
    f a -> b -> c
    g = (a -> b -> c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, 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 -> b -> c
    f a -> b -> c
    g Gen (a, b)
    forall a. Arbitrary a => Gen a
    arbitrary (a, b) -> [(a, b)]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenFirstSucceedsOnGen ::
      (Show a, Show b, Eq b, CanFail f) =>
      (a -> f b) ->
      (a -> b) ->
      Gen a ->
      (a -> [a]) ->
      Property
    equivalentWhenFirstSucceedsOnGen :: forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenFirstSucceedsOnGen a -> f b
    f a -> b
    g Gen a
    gen a -> [a]
    s =
      Gen a -> (a -> [a]) -> (a -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen a
    gen a -> [a]
    s ((a -> Expectation) -> Property) -> (a -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \a
    a ->
        case f b -> Maybe b
    forall a. f a -> Maybe a
    forall (f :: * -> *) a. CanFail f => f a -> Maybe a
    resultIfSucceeded (a -> f b
    f a
    a) of
          Maybe b
    Nothing -> () -> Expectation
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- fine
          Just b
    r -> b
    r b -> b -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b
    g a
    a

    equivalentWhenFirstSucceedsOnArbitrary ::
      (Show a, Arbitrary a, Show b, Eq b, CanFail f) =>
      (a -> f b) ->
      (a -> b) ->
      Property
    equivalentWhenFirstSucceedsOnArbitrary :: forall a b (f :: * -> *).
    (Show a, Arbitrary a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> b) -> Property
    equivalentWhenFirstSucceedsOnArbitrary a -> f b
    f a -> b
    g =
      (a -> f b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenFirstSucceedsOnGen a -> f b
    f a -> b
    g Gen a
    forall a. Arbitrary a => Gen a
    arbitrary a -> [a]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenFirstSucceeds ::
      (Show a, GenValid a, Show b, Eq b, CanFail f) =>
      (a -> f b) ->
      (a -> b) ->
      Property
    equivalentWhenFirstSucceeds :: forall a b (f :: * -> *).
    (Show a, GenValid a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> b) -> Property
    equivalentWhenFirstSucceeds a -> f b
    f a -> b
    g =
      (a -> f b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenFirstSucceedsOnGen a -> f b
    f a -> b
    g Gen a
    forall a. GenValid a => Gen a
    genValid a -> [a]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentWhenFirstSucceedsOnGens2 ::
      (Show a, Show b, Show c, Eq c, CanFail f) =>
      (a -> b -> f c) ->
      (a -> b -> c) ->
      Gen (a, b) ->
      ((a, b) -> [(a, b)]) ->
      Property
    equivalentWhenFirstSucceedsOnGens2 :: forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> f c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
    equivalentWhenFirstSucceedsOnGens2 a -> b -> f c
    f a -> b -> c
    g Gen (a, b)
    gen (a, b) -> [(a, b)]
    s =
      Gen (a, b)
    -> ((a, b) -> [(a, b)]) -> ((a, b) -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen (a, b)
    gen (a, b) -> [(a, b)]
    s (((a, b) -> Expectation) -> Property)
    -> ((a, b) -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, b
    b) ->
        case f c -> Maybe c
    forall a. f a -> Maybe a
    forall (f :: * -> *) a. CanFail f => f a -> Maybe a
    resultIfSucceeded (a -> b -> f c
    f a
    a b
    b) of
          Maybe c
    Nothing -> () -> Expectation
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- fine
          Just c
    rs -> c
    rs c -> c -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b -> c
    g a
    a b
    b

    equivalentWhenFirstSucceedsOnArbitrary2 ::
      ( Show a,
        Arbitrary a,
        Show b,
        Arbitrary b,
        Show c,
        Eq c,
        CanFail f
      ) =>
      (a -> b -> f c) ->
      (a -> b -> c) ->
      Property
    equivalentWhenFirstSucceedsOnArbitrary2 :: forall a b c (f :: * -> *).
    (Show a, Arbitrary a, Show b, Arbitrary b, Show c, Eq c,
     CanFail f) =>
    (a -> b -> f c) -> (a -> b -> c) -> Property
    equivalentWhenFirstSucceedsOnArbitrary2 a -> b -> f c
    f a -> b -> c
    g =
      (a -> b -> f c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
    forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> f c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
    equivalentWhenFirstSucceedsOnGens2 a -> b -> f c
    f a -> b -> c
    g Gen (a, b)
    forall a. Arbitrary a => Gen a
    arbitrary (a, b) -> [(a, b)]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenFirstSucceeds2 ::
      ( Show a,
        GenValid a,
        Show b,
        GenValid b,
        Show c,
        Eq c,
        CanFail f
      ) =>
      (a -> b -> f c) ->
      (a -> b -> c) ->
      Property
    equivalentWhenFirstSucceeds2 :: forall a b c (f :: * -> *).
    (Show a, GenValid a, Show b, GenValid b, Show c, Eq c,
     CanFail f) =>
    (a -> b -> f c) -> (a -> b -> c) -> Property
    equivalentWhenFirstSucceeds2 a -> b -> f c
    f a -> b -> c
    g =
      (a -> b -> f c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
    forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> f c)
    -> (a -> b -> c) -> Gen (a, b) -> ((a, b) -> [(a, b)]) -> Property
    equivalentWhenFirstSucceedsOnGens2 a -> b -> f c
    f a -> b -> c
    g Gen (a, b)
    forall a. GenValid a => Gen a
    genValid (a, b) -> [(a, b)]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentWhenSecondSucceedsOnGen ::
      (Show a, Show b, Eq b, CanFail f) =>
      (a -> b) ->
      (a -> f b) ->
      Gen a ->
      (a -> [a]) ->
      Property
    equivalentWhenSecondSucceedsOnGen :: forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenSecondSucceedsOnGen a -> b
    f a -> f b
    g Gen a
    gen a -> [a]
    s =
      Gen a -> (a -> [a]) -> (a -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen a
    gen a -> [a]
    s ((a -> Expectation) -> Property) -> (a -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \a
    a ->
        case f b -> Maybe b
    forall a. f a -> Maybe a
    forall (f :: * -> *) a. CanFail f => f a -> Maybe a
    resultIfSucceeded (a -> f b
    g a
    a) of
          Maybe b
    Nothing -> () -> Expectation
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- fine
          Just b
    r -> b
    r b -> b -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b
    f a
    a

    equivalentWhenSecondSucceedsOnArbitrary ::
      (Show a, Arbitrary a, Show b, Eq b, CanFail f) =>
      (a -> b) ->
      (a -> f b) ->
      Property
    equivalentWhenSecondSucceedsOnArbitrary :: forall a b (f :: * -> *).
    (Show a, Arbitrary a, Show b, Eq b, CanFail f) =>
    (a -> b) -> (a -> f b) -> Property
    equivalentWhenSecondSucceedsOnArbitrary a -> b
    f a -> f b
    g =
      (a -> b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenSecondSucceedsOnGen a -> b
    f a -> f b
    g Gen a
    forall a. Arbitrary a => Gen a
    arbitrary a -> [a]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenSecondSucceeds ::
      (Show a, GenValid a, Show b, Eq b, CanFail f) =>
      (a -> b) ->
      (a -> f b) ->
      Property
    equivalentWhenSecondSucceeds :: forall a b (f :: * -> *).
    (Show a, GenValid a, Show b, Eq b, CanFail f) =>
    (a -> b) -> (a -> f b) -> Property
    equivalentWhenSecondSucceeds a -> b
    f a -> f b
    g =
      (a -> b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenSecondSucceedsOnGen a -> b
    f a -> f b
    g Gen a
    forall a. GenValid a => Gen a
    genValid a -> [a]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentWhenSecondSucceedsOnGens2 ::
      (Show a, Show b, Show c, Eq c, CanFail f) =>
      (a -> b -> c) ->
      (a -> b -> f c) ->
      Gen (a, b) ->
      ((a, b) -> [(a, b)]) ->
      Property
    equivalentWhenSecondSucceedsOnGens2 :: forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    equivalentWhenSecondSucceedsOnGens2 a -> b -> c
    f a -> b -> f c
    g Gen (a, b)
    gen (a, b) -> [(a, b)]
    s =
      Gen (a, b)
    -> ((a, b) -> [(a, b)]) -> ((a, b) -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen (a, b)
    gen (a, b) -> [(a, b)]
    s (((a, b) -> Expectation) -> Property)
    -> ((a, b) -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, b
    b) ->
        case f c -> Maybe c
    forall a. f a -> Maybe a
    forall (f :: * -> *) a. CanFail f => f a -> Maybe a
    resultIfSucceeded (a -> b -> f c
    g a
    a b
    b) of
          Maybe c
    Nothing -> () -> Expectation
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- fine
          Just c
    rs -> c
    rs c -> c -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b -> c
    f a
    a b
    b

    equivalentWhenSecondSucceedsOnArbitrary2 ::
      ( Show a,
        Arbitrary a,
        Show b,
        Arbitrary b,
        Show c,
        Eq c,
        CanFail f
      ) =>
      (a -> b -> c) ->
      (a -> b -> f c) ->
      Property
    equivalentWhenSecondSucceedsOnArbitrary2 :: forall a b c (f :: * -> *).
    (Show a, Arbitrary a, Show b, Arbitrary b, Show c, Eq c,
     CanFail f) =>
    (a -> b -> c) -> (a -> b -> f c) -> Property
    equivalentWhenSecondSucceedsOnArbitrary2 a -> b -> c
    f a -> b -> f c
    g =
      (a -> b -> c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    equivalentWhenSecondSucceedsOnGens2 a -> b -> c
    f a -> b -> f c
    g Gen (a, b)
    forall a. Arbitrary a => Gen a
    arbitrary (a, b) -> [(a, b)]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenSecondSucceeds2 ::
      ( Show a,
        GenValid a,
        Show b,
        GenValid b,
        Show c,
        Eq c,
        CanFail f
      ) =>
      (a -> b -> c) ->
      (a -> b -> f c) ->
      Property
    equivalentWhenSecondSucceeds2 :: forall a b c (f :: * -> *).
    (Show a, GenValid a, Show b, GenValid b, Show c, Eq c,
     CanFail f) =>
    (a -> b -> c) -> (a -> b -> f c) -> Property
    equivalentWhenSecondSucceeds2 a -> b -> c
    f a -> b -> f c
    g =
      (a -> b -> c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    equivalentWhenSecondSucceedsOnGens2 a -> b -> c
    f a -> b -> f c
    g Gen (a, b)
    forall a. GenValid a => Gen a
    genValid (a, b) -> [(a, b)]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentWhenSucceedOnGen ::
      (Show a, Show b, Eq b, CanFail f) =>
      (a -> f b) ->
      (a -> f b) ->
      Gen a ->
      (a -> [a]) ->
      Property
    equivalentWhenSucceedOnGen :: forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenSucceedOnGen a -> f b
    f a -> f b
    g Gen a
    gen a -> [a]
    s =
      Gen a -> (a -> [a]) -> (a -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen a
    gen a -> [a]
    s ((a -> Expectation) -> Property) -> (a -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \a
    a ->
        case do
          fa <- f b -> Maybe b
    forall a. f a -> Maybe a
    forall (f :: * -> *) a. CanFail f => f a -> Maybe a
    resultIfSucceeded (f b -> Maybe b) -> f b -> Maybe b
    forall a b. (a -> b) -> a -> b
    $ a -> f b
    f a
    a
          ga <- resultIfSucceeded $ g a
          return (fa, ga) of
          Maybe (b, b)
    Nothing -> () -> Expectation
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- fine
          Just (b
    fa, b
    ga) -> b
    fa b -> b -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` b
    ga

    equivalentWhenSucceed ::
      (Show a, GenValid a, Show b, Eq b, CanFail f) =>
      (a -> f b) ->
      (a -> f b) ->
      Property
    equivalentWhenSucceed :: forall a b (f :: * -> *).
    (Show a, GenValid a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> f b) -> Property
    equivalentWhenSucceed a -> f b
    f a -> f b
    g =
      (a -> f b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenSucceedOnGen a -> f b
    f a -> f b
    g Gen a
    forall a. GenValid a => Gen a
    genValid a -> [a]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentWhenSucceedOnArbitrary ::
      (Show a, Arbitrary a, Show b, Eq b, CanFail f) =>
      (a -> f b) ->
      (a -> f b) ->
      Property
    equivalentWhenSucceedOnArbitrary :: forall a b (f :: * -> *).
    (Show a, Arbitrary a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> f b) -> Property
    equivalentWhenSucceedOnArbitrary a -> f b
    f a -> f b
    g =
      (a -> f b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    forall a b (f :: * -> *).
    (Show a, Show b, Eq b, CanFail f) =>
    (a -> f b) -> (a -> f b) -> Gen a -> (a -> [a]) -> Property
    equivalentWhenSucceedOnGen a -> f b
    f a -> f b
    g Gen a
    forall a. Arbitrary a => Gen a
    arbitrary a -> [a]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenSucceedOnGens2 ::
      (Show a, Show b, Show c, Eq c, CanFail f) =>
      (a -> b -> f c) ->
      (a -> b -> f c) ->
      Gen (a, b) ->
      ((a, b) -> [(a, b)]) ->
      Property
    equivalentWhenSucceedOnGens2 :: forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> f c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    equivalentWhenSucceedOnGens2 a -> b -> f c
    f a -> b -> f c
    g Gen (a, b)
    gen (a, b) -> [(a, b)]
    s =
      Gen (a, b)
    -> ((a, b) -> [(a, b)]) -> ((a, b) -> Expectation) -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen (a, b)
    gen (a, b) -> [(a, b)]
    s (((a, b) -> Expectation) -> Property)
    -> ((a, b) -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, b
    b) ->
        case do
          fab <- f c -> Maybe c
    forall a. f a -> Maybe a
    forall (f :: * -> *) a. CanFail f => f a -> Maybe a
    resultIfSucceeded (f c -> Maybe c) -> f c -> Maybe c
    forall a b. (a -> b) -> a -> b
    $ a -> b -> f c
    f a
    a b
    b
          gab <- resultIfSucceeded $ g a b
          return (fab, gab) of
          Maybe (c, c)
    Nothing -> () -> Expectation
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- fine
          Just (c
    fab, c
    gab) -> c
    fab c -> c -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` c
    gab

    equivalentWhenSucceedOnArbitrary2 ::
      ( Show a,
        Arbitrary a,
        Show b,
        Arbitrary b,
        Show c,
        Eq c,
        CanFail f
      ) =>
      (a -> b -> f c) ->
      (a -> b -> f c) ->
      Property
    equivalentWhenSucceedOnArbitrary2 :: forall a b c (f :: * -> *).
    (Show a, Arbitrary a, Show b, Arbitrary b, Show c, Eq c,
     CanFail f) =>
    (a -> b -> f c) -> (a -> b -> f c) -> Property
    equivalentWhenSucceedOnArbitrary2 a -> b -> f c
    f a -> b -> f c
    g =
      (a -> b -> f c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> f c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    equivalentWhenSucceedOnGens2 a -> b -> f c
    f a -> b -> f c
    g Gen (a, b)
    forall a. Arbitrary a => Gen a
    arbitrary (a, b) -> [(a, b)]
    forall a. Arbitrary a => a -> [a]
    shrink

    equivalentWhenSucceed2 ::
      ( Show a,
        GenValid a,
        Show b,
        GenValid b,
        Show c,
        Eq c,
        CanFail f
      ) =>
      (a -> b -> f c) ->
      (a -> b -> f c) ->
      Property
    equivalentWhenSucceed2 :: forall a b c (f :: * -> *).
    (Show a, GenValid a, Show b, GenValid b, Show c, Eq c,
     CanFail f) =>
    (a -> b -> f c) -> (a -> b -> f c) -> Property
    equivalentWhenSucceed2 a -> b -> f c
    f a -> b -> f c
    g =
      (a -> b -> f c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    forall a b c (f :: * -> *).
    (Show a, Show b, Show c, Eq c, CanFail f) =>
    (a -> b -> f c)
    -> (a -> b -> f c)
    -> Gen (a, b)
    -> ((a, b) -> [(a, b)])
    -> Property
    equivalentWhenSucceedOnGens2 a -> b -> f c
    f a -> b -> f c
    g Gen (a, b)
    forall a. GenValid a => Gen a
    genValid (a, b) -> [(a, b)]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentOnGens3 ::
      (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 :: 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 a -> b -> c -> d
    f a -> b -> c -> d
    g Gen (a, b, c)
    gen (a, b, c) -> [(a, b, c)]
    s =
      Gen (a, b, c)
    -> ((a, b, c) -> [(a, b, c)])
    -> ((a, b, c) -> Expectation)
    -> Property
    forall a prop.
    (Show a, Testable prop) =>
    Gen a -> (a -> [a]) -> (a -> prop) -> Property
    forAllShrink Gen (a, b, c)
    gen (a, b, c) -> [(a, b, c)]
    s (((a, b, c) -> Expectation) -> Property)
    -> ((a, b, c) -> Expectation) -> Property
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, b
    b, c
    c) -> a -> b -> c -> d
    f a
    a b
    b c
    c d -> d -> Expectation
    forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
    `shouldBe` a -> b -> c -> d
    g a
    a b
    b c
    c

    equivalent3 ::
      ( Show a,
        GenValid a,
        Show b,
        GenValid b,
        Show c,
        GenValid c,
        Show d,
        Eq d
      ) =>
      (a -> b -> c -> d) ->
      (a -> b -> c -> d) ->
      Property
    equivalent3 :: forall a b c d.
    (Show a, GenValid a, Show b, GenValid b, Show c, GenValid c,
     Show d, Eq d) =>
    (a -> b -> c -> d) -> (a -> b -> c -> d) -> Property
    equivalent3 a -> b -> c -> d
    f a -> b -> c -> d
    g = (a -> b -> c -> d)
    -> (a -> b -> c -> d)
    -> Gen (a, b, c)
    -> ((a, b, c) -> [(a, b, 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 a -> b -> c -> d
    f a -> b -> c -> d
    g Gen (a, b, c)
    forall a. GenValid a => Gen a
    genValid (a, b, c) -> [(a, b, c)]
    forall a. GenValid a => a -> [a]
    shrinkValid

    equivalentOnArbitrary3 ::
      ( Show a,
        Arbitrary a,
        Show b,
        Arbitrary b,
        Show c,
        Arbitrary c,
        Show d,
        Eq d
      ) =>
      (a -> b -> c -> d) ->
      (a -> b -> c -> d) ->
      Property
    equivalentOnArbitrary3 :: forall a b c d.
    (Show a, Arbitrary a, Show b, Arbitrary b, Show c, Arbitrary c,
     Show d, Eq d) =>
    (a -> b -> c -> d) -> (a -> b -> c -> d) -> Property
    equivalentOnArbitrary3 a -> b -> c -> d
    f a -> b -> c -> d
    g = (a -> b -> c -> d)
    -> (a -> b -> c -> d)
    -> Gen (a, b, c)
    -> ((a, b, c) -> [(a, b, 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 a -> b -> c -> d
    f a -> b -> c -> d
    g Gen (a, b, c)
    forall a. Arbitrary a => Gen a
    arbitrary (a, b, c) -> [(a, b, c)]
    forall a. Arbitrary a => a -> [a]
    shrink