-- |
-- The general procedure for generating functions of type @A -> B@ looks something like this:
--
-- @
-- {-\# language DeriveGeneric \#-}
-- {-\# language TypeApplications \#-}
--
-- import Hedgehog
-- import Hedgehog.Function
--
-- data A = ...
--   deriving (Generic, ...)
--
-- instance Arg A
-- instance Vary A
--
-- genB :: MonadGen m => m B
-- genB = ...
--
-- prop_test :: Property
-- prop_test =
--   property $ do
--     f <- forAllFn $ fn @A genB
--     ...
-- @
--
-- Here's an example of how to use the library to test the "fmap composition" law.
--
-- @ScopedTypeVariables@ and @TypeApplications@ are recommended for ease of use. @RankNTypes@
-- is only necessary for this example.
--
-- @
-- {-\# language RankNTypes \#-}
-- {-\# language ScopedTypeVariables, TypeApplications \#-}
--
-- import Hedgehog
-- import Hedgehog.Function
-- import qualified Hedgehog.Gen as Gen
-- import qualified Hedgehog.Range as Range
--
-- map_compose
--   :: forall f a b c
--    . ( Functor f
--      , Show (f a)
--      , Show a, Arg a, Vary a
--      , Show b, Arg b, Vary b
--      , Show c
--      , Eq (f c)
--      , Show (f c)
--      )
--   => (forall x. Gen x -> Gen (f x))
--   -> Gen a
--   -> Gen b
--   -> Gen c
--   -> Property
-- map_compose genF genA genB genC =
--   property $ do
--     g <- forAllFn $ fn \@a genB
--     f <- forAllFn $ fn \@b genC
--     xs <- forAll $ genF genA
--     fmap (f . g) xs === fmap f (fmap g xs)
--
-- prop_map_list :: Property
-- prop_map_list =
--   map_compose
--     (Gen.list (Range.constant 0 100))
--     Gen.bool
--     Gen.bool
--     Gen.bool
-- @

module Hedgehog.Function
  ( module GHC.Generics
  , Fn
  -- * Generation
  , forAllFn
  , apply
  , fn
  , fnWith
  -- * Building
  , gbuild
  , via
  , buildIntegral
  , Arg(..)
  -- * Varying
  , module Data.Functor.Contravariant
  , module Data.Functor.Contravariant.Divisible
  , CoGenT
  , CoGen
  , gvary
  , varyIntegral
  , Vary(..)
  )
where

import GHC.Generics
import Data.Functor.Contravariant
import Data.Functor.Contravariant.Divisible
import Hedgehog.Function.Internal