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

    -- | Tests for Arbitrary instances involving Validity
    --
    -- You will need @TypeApplications@ to use these.
    module Test.Validity.Arbitrary
      ( arbitrarySpec,
        arbitraryGeneratesOnlyValid,
      )
    where

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

    -- | A @Spec@ that specifies that @arbitrary@ only generates data that
    -- satisfy @isValid@
    --
    -- Example usage:
    --
    -- > arbitrarySpec @Int
    arbitrarySpec ::
      forall a.
      (Typeable a, Show a, Validity a, Arbitrary a) =>
      Spec
    arbitrarySpec :: forall a. (Typeable a, Show a, Validity a, Arbitrary a) => Spec
    arbitrarySpec = do
      let name :: String
    name = forall a. Typeable a => String
    forall {k} (a :: k). Typeable a => String
    nameOf @a
      String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String
    "Arbitrary " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name) (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $
        String -> Spec -> Spec
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
    describe (String
    "arbitrary :: Gen " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name) (Spec -> Spec) -> Spec -> Spec
    forall a b. (a -> b) -> a -> b
    $
          String -> Property -> SpecM (Arg Property) ()
    forall a.
    (HasCallStack, Example a) =>
    String -> a -> SpecWith (Arg a)
    it String
    "only generates valid values" (Property -> SpecM (Arg Property) ())
    -> Property -> SpecM (Arg Property) ()
    forall a b. (a -> b) -> a -> b
    $
            forall a. (Show a, Validity a, Arbitrary a) => Property
    arbitraryGeneratesOnlyValid @a

    -- | @arbitrary@ only generates valid data
    --
    -- prop> arbitraryGeneratesOnlyValid @Int
    arbitraryGeneratesOnlyValid ::
      forall a.
      (Show a, Validity a, Arbitrary a) =>
      Property
    arbitraryGeneratesOnlyValid :: forall a. (Show a, Validity a, Arbitrary a) => Property
    arbitraryGeneratesOnlyValid = forall a. (Show a, Validity a) => Gen a -> Property
    genGeneratesValid @a Gen a
    forall a. Arbitrary a => Gen a
    arbitrary