packages feed

hedgehog 0.4.1 → 0.5

raw patch · 15 files changed

+1665/−736 lines, 15 filesdep +lifted-asyncdep +monad-controldep ~ansi-terminaldep ~concurrent-outputPVP ok

version bump matches the API change (PVP)

Dependencies added: lifted-async, monad-control

Dependency ranges changed: ansi-terminal, concurrent-output

API changes (from Hackage documentation)

- Hedgehog: [Symbolic] :: Typeable a => Var -> Symbolic a
- Hedgehog: data Gen m a
- Hedgehog: data Test m a
- Hedgehog: liftCatch :: (MonadCatch m, HasCallStack) => m a -> Test m a
- Hedgehog: liftCatchIO :: (MonadIO m, HasCallStack) => IO a -> Test m a
- Hedgehog: liftEither :: (Monad m, Show x, HasCallStack) => Either x a -> Test m a
- Hedgehog: liftExceptT :: (Monad m, Show x, HasCallStack) => ExceptT x m a -> Test m a
- Hedgehog: withCatch :: (MonadCatch m, HasCallStack) => Test m a -> Test m a
- Hedgehog: withExceptT :: (Monad m, Show x, HasCallStack) => Test (ExceptT x m) a -> Test m a
- Hedgehog: withResourceT :: MonadResourceBase m => Test (ResourceT m) a -> Test m a
- Hedgehog.Gen: actions :: (Monad n, Monad m) => Range Int -> (forall v. state v) -> [Command n m state] -> Gen n [Action m state]
- Hedgehog.Gen: data Gen m a
- Hedgehog.Internal.Exception: TypedException :: SomeException -> TypedException
- Hedgehog.Internal.Exception: instance GHC.Show.Show Hedgehog.Internal.Exception.TypedException
- Hedgehog.Internal.Exception: newtype TypedException
- Hedgehog.Internal.Gen: Gen :: (Size -> Seed -> Tree (MaybeT m) a) -> Gen m a
- Hedgehog.Internal.Gen: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Gen.Gen
- Hedgehog.Internal.Gen: instance Control.Monad.Morph.MMonad Hedgehog.Internal.Gen.Gen
- Hedgehog.Internal.Gen: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Gen.Gen
- Hedgehog.Internal.Gen: instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.Alternative (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Hedgehog.Internal.Gen.Gen m)
- Hedgehog.Internal.Gen: instance Hedgehog.Internal.Distributive.Distributive Hedgehog.Internal.Gen.Gen
- Hedgehog.Internal.Gen: mapGen :: (Tree (MaybeT m) a -> Tree (MaybeT n) b) -> Gen m a -> Gen n b
- Hedgehog.Internal.Gen: newtype Gen m a
- Hedgehog.Internal.Gen: runGen :: Size -> Seed -> Gen m a -> Tree (MaybeT m) a
- Hedgehog.Internal.Property: Test :: ExceptT Failure (WriterT [Log] (Gen m)) a -> Test m a
- Hedgehog.Internal.Property: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Property.Test
- Hedgehog.Internal.Property: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Property.Test
- Hedgehog.Internal.Property: instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Alternative (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Hedgehog.Internal.Property.Test m)
- Hedgehog.Internal.Property: instance Hedgehog.Internal.Distributive.Distributive Hedgehog.Internal.Property.Test
- Hedgehog.Internal.Property: liftCatch :: (MonadCatch m, HasCallStack) => m a -> Test m a
- Hedgehog.Internal.Property: liftCatchIO :: (MonadIO m, HasCallStack) => IO a -> Test m a
- Hedgehog.Internal.Property: liftEither :: (Monad m, Show x, HasCallStack) => Either x a -> Test m a
- Hedgehog.Internal.Property: liftExceptT :: (Monad m, Show x, HasCallStack) => ExceptT x m a -> Test m a
- Hedgehog.Internal.Property: newtype Test m a
- Hedgehog.Internal.Property: withCatch :: (MonadCatch m, HasCallStack) => Test m a -> Test m a
- Hedgehog.Internal.Property: withExceptT :: (Monad m, Show x, HasCallStack) => Test (ExceptT x m) a -> Test m a
- Hedgehog.Internal.Property: withResourceT :: MonadResourceBase m => Test (ResourceT m) a -> Test m a
- Hedgehog.Internal.Region: forceRegion :: LiftRegion m => Region -> String -> m ()
- Hedgehog.Internal.Region: newRegion :: LiftRegion m => m Region
- Hedgehog.Internal.State: actions :: (Monad n, Monad m) => Range Int -> (forall v. state v) -> [Command n m state] -> Gen n [Action m state]
- Hedgehog.Internal.State: execute :: (HasCallStack, Monad m) => (state Concrete, Environment) -> Action m state -> Test m (state Concrete, Environment)
- Hedgehog.Internal.State: instance GHC.Classes.Eq Hedgehog.Internal.State.Var
- Hedgehog.Internal.State: instance GHC.Classes.Ord Hedgehog.Internal.State.Var
- Hedgehog.Internal.State: instance GHC.Num.Num Hedgehog.Internal.State.Var
- Hedgehog.Internal.State: instance GHC.Show.Show Hedgehog.Internal.State.Var
- Hedgehog.Internal.State: newtype Var
+ Hedgehog: Parallel :: [Action m state] -> [Action m state] -> [Action m state] -> Parallel m state
+ Hedgehog: Sequential :: [Action m state] -> Sequential m state
+ Hedgehog: Var :: (v a) -> Var a v
+ Hedgehog: [parallelBranch1] :: Parallel m state -> [Action m state]
+ Hedgehog: [parallelBranch2] :: Parallel m state -> [Action m state]
+ Hedgehog: [parallelPrefix] :: Parallel m state -> [Action m state]
+ Hedgehog: [sequentialActions] :: Sequential m state -> [Action m state]
+ Hedgehog: class Monad m => MonadGen m
+ Hedgehog: class Monad m => MonadTest m
+ Hedgehog: concrete :: Var a Concrete -> a
+ Hedgehog: data GenT m a
+ Hedgehog: data Parallel m state
+ Hedgehog: data PropertyT m a
+ Hedgehog: data Sequential m state
+ Hedgehog: data ShrinkRetries
+ Hedgehog: data TestT m a
+ Hedgehog: eval :: (MonadTest m, HasCallStack) => a -> m a
+ Hedgehog: evalEither :: (MonadTest m, Show x, HasCallStack) => Either x a -> m a
+ Hedgehog: evalExceptT :: (MonadTest m, Show x, HasCallStack) => ExceptT x m a -> m a
+ Hedgehog: evalIO :: (MonadTest m, MonadIO m, HasCallStack) => IO a -> m a
+ Hedgehog: evalM :: (MonadTest m, MonadCatch m, HasCallStack) => m a -> m a
+ Hedgehog: executeParallel :: (MonadTest m, MonadCatch m, MonadBaseControl IO m, HasCallStack) => (forall v. state v) -> Parallel m state -> m ()
+ Hedgehog: freezeGen :: MonadGen m => m a -> m (a, m a)
+ Hedgehog: liftGen :: MonadGen m => Gen a -> m a
+ Hedgehog: liftTest :: MonadTest m => Test a -> m a
+ Hedgehog: opaque :: Var (Opaque a) Concrete -> a
+ Hedgehog: pruneGen :: MonadGen m => m a -> m a
+ Hedgehog: scaleGen :: MonadGen m => (Size -> Size) -> m a -> m a
+ Hedgehog: shrinkGen :: MonadGen m => (a -> [a]) -> m a -> m a
+ Hedgehog: test :: Monad m => TestT m a -> PropertyT m a
+ Hedgehog: type Gen = GenT Identity
+ Hedgehog: type Test = TestT Identity
+ Hedgehog: withRetries :: ShrinkRetries -> Property -> Property
+ Hedgehog.Gen: freeze :: MonadGen m => m a -> m (a, m a)
+ Hedgehog.Gen: lift :: MonadGen m => Gen a -> m a
+ Hedgehog.Gen: parallel :: (MonadGen n, MonadTest m) => Range Int -> Range Int -> (forall v. state v) -> [Command n m state] -> n (Parallel m state)
+ Hedgehog.Gen: sequential :: (MonadGen n, MonadTest m) => Range Int -> (forall v. state v) -> [Command n m state] -> n (Sequential m state)
+ Hedgehog.Internal.Exception: tryEvaluate :: a -> Either SomeException a
+ Hedgehog.Internal.Gen: GenT :: (Size -> Seed -> Tree (MaybeT m) a) -> GenT m a
+ Hedgehog.Internal.Gen: class Monad m => MonadGen m
+ Hedgehog.Internal.Gen: ensure :: MonadGen m => (a -> Bool) -> m a -> m a
+ Hedgehog.Internal.Gen: freezeGen :: MonadGen m => m a -> m (a, m a)
+ Hedgehog.Internal.Gen: instance (Hedgehog.Internal.Gen.MonadGen m, GHC.Base.Monoid w) => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
+ Hedgehog.Internal.Gen: instance (Hedgehog.Internal.Gen.MonadGen m, GHC.Base.Monoid w) => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.RWS.Strict.RWST r w s m)
+ Hedgehog.Internal.Gen: instance (Hedgehog.Internal.Gen.MonadGen m, GHC.Base.Monoid w) => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Writer.Lazy.WriterT w m)
+ Hedgehog.Internal.Gen: instance (Hedgehog.Internal.Gen.MonadGen m, GHC.Base.Monoid w) => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Writer.Strict.WriterT w m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Gen.GenT
+ Hedgehog.Internal.Gen: instance Control.Monad.Morph.MMonad Hedgehog.Internal.Gen.GenT
+ Hedgehog.Internal.Gen: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Gen.GenT
+ Hedgehog.Internal.Gen: instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.Alternative (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance GHC.Base.Monad m => Hedgehog.Internal.Gen.MonadGen (Hedgehog.Internal.Gen.GenT m)
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Distributive.Distributive Hedgehog.Internal.Gen.GenT
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Except.ExceptT x m)
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Identity.IdentityT m)
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Maybe.MaybeT m)
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Reader.ReaderT r m)
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.State.Lazy.StateT s m)
+ Hedgehog.Internal.Gen: instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.State.Strict.StateT s m)
+ Hedgehog.Internal.Gen: lift :: MonadGen m => Gen a -> m a
+ Hedgehog.Internal.Gen: liftGen :: MonadGen m => Gen a -> m a
+ Hedgehog.Internal.Gen: mapGenT :: (Tree (MaybeT m) a -> Tree (MaybeT n) b) -> GenT m a -> GenT n b
+ Hedgehog.Internal.Gen: newtype GenT m a
+ Hedgehog.Internal.Gen: pruneGen :: MonadGen m => m a -> m a
+ Hedgehog.Internal.Gen: runGenT :: Size -> Seed -> GenT m a -> Tree (MaybeT m) a
+ Hedgehog.Internal.Gen: scaleGen :: MonadGen m => (Size -> Size) -> m a -> m a
+ Hedgehog.Internal.Gen: shrinkGen :: MonadGen m => (a -> [a]) -> m a -> m a
+ Hedgehog.Internal.Gen: type Gen = GenT Identity
+ Hedgehog.Internal.Property: PropertyT :: TestT (GenT m) a -> PropertyT m a
+ Hedgehog.Internal.Property: ShrinkRetries :: Int -> ShrinkRetries
+ Hedgehog.Internal.Property: TestT :: ExceptT Failure (WriterT [Log] m) a -> TestT m a
+ Hedgehog.Internal.Property: [propertyShrinkRetries] :: PropertyConfig -> !ShrinkRetries
+ Hedgehog.Internal.Property: [unPropertyT] :: PropertyT m a -> TestT (GenT m) a
+ Hedgehog.Internal.Property: class Monad m => MonadTest m
+ Hedgehog.Internal.Property: eval :: (MonadTest m, HasCallStack) => a -> m a
+ Hedgehog.Internal.Property: evalEither :: (MonadTest m, Show x, HasCallStack) => Either x a -> m a
+ Hedgehog.Internal.Property: evalExceptT :: (MonadTest m, Show x, HasCallStack) => ExceptT x m a -> m a
+ Hedgehog.Internal.Property: evalIO :: (MonadTest m, MonadIO m, HasCallStack) => IO a -> m a
+ Hedgehog.Internal.Property: evalM :: (MonadTest m, MonadCatch m, HasCallStack) => m a -> m a
+ Hedgehog.Internal.Property: failDiff :: (MonadTest m, Show a, Show b, HasCallStack) => a -> b -> m ()
+ Hedgehog.Internal.Property: failException :: (MonadTest m, HasCallStack) => SomeException -> m a
+ Hedgehog.Internal.Property: forAllT :: (Monad m, Show a, HasCallStack) => GenT m a -> PropertyT m a
+ Hedgehog.Internal.Property: forAllWithT :: (Monad m, HasCallStack) => (a -> String) -> GenT m a -> PropertyT m a
+ Hedgehog.Internal.Property: instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
+ Hedgehog.Internal.Property: instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.RWS.Strict.RWST r w s m)
+ Hedgehog.Internal.Property: instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Writer.Lazy.WriterT w m)
+ Hedgehog.Internal.Property: instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Writer.Strict.WriterT w m)
+ Hedgehog.Internal.Property: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Property.PropertyT
+ Hedgehog.Internal.Property: instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Property.TestT
+ Hedgehog.Internal.Property: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Property.PropertyT
+ Hedgehog.Internal.Property: instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Property.TestT
+ Hedgehog.Internal.Property: instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance Control.Monad.Trans.Control.MonadTransControl Hedgehog.Internal.Property.TestT
+ Hedgehog.Internal.Property: instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Monad m => Hedgehog.Internal.Property.MonadTest (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance GHC.Base.Monad m => Hedgehog.Internal.Property.MonadTest (Hedgehog.Internal.Property.TestT m)
+ Hedgehog.Internal.Property: instance GHC.Base.MonadPlus m => GHC.Base.Alternative (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Hedgehog.Internal.Property.PropertyT m)
+ Hedgehog.Internal.Property: instance GHC.Classes.Eq Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance GHC.Classes.Ord Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance GHC.Enum.Enum Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance GHC.Num.Num Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance GHC.Real.Integral Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance GHC.Real.Real Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance GHC.Show.Show Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Distributive.Distributive Hedgehog.Internal.Property.PropertyT
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Distributive.Distributive Hedgehog.Internal.Property.TestT
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Cont.ContT r m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Except.ExceptT x m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Identity.IdentityT m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Maybe.MaybeT m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Reader.ReaderT r m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Resource.Internal.ResourceT m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.State.Lazy.StateT s m)
+ Hedgehog.Internal.Property: instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.State.Strict.StateT s m)
+ Hedgehog.Internal.Property: instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.ShrinkRetries
+ Hedgehog.Internal.Property: liftTest :: MonadTest m => Test a -> m a
+ Hedgehog.Internal.Property: mkTest :: (Either Failure a, [Log]) -> Test a
+ Hedgehog.Internal.Property: mkTestT :: m (Either Failure a, [Log]) -> TestT m a
+ Hedgehog.Internal.Property: newtype PropertyT m a
+ Hedgehog.Internal.Property: newtype ShrinkRetries
+ Hedgehog.Internal.Property: newtype TestT m a
+ Hedgehog.Internal.Property: runTestT :: TestT m a -> m (Either Failure a, [Log])
+ Hedgehog.Internal.Property: test :: Monad m => TestT m a -> PropertyT m a
+ Hedgehog.Internal.Property: type Test = TestT Identity
+ Hedgehog.Internal.Property: withRetries :: ShrinkRetries -> Property -> Property
+ Hedgehog.Internal.Region: newOpenRegion :: LiftRegion m => m Region
+ Hedgehog.Internal.Region: openRegion :: LiftRegion m => Region -> String -> m ()
+ Hedgehog.Internal.State: Name :: Int -> Name
+ Hedgehog.Internal.State: Parallel :: [Action m state] -> [Action m state] -> [Action m state] -> Parallel m state
+ Hedgehog.Internal.State: Sequential :: [Action m state] -> Sequential m state
+ Hedgehog.Internal.State: [parallelBranch1] :: Parallel m state -> [Action m state]
+ Hedgehog.Internal.State: [parallelBranch2] :: Parallel m state -> [Action m state]
+ Hedgehog.Internal.State: [parallelPrefix] :: Parallel m state -> [Action m state]
+ Hedgehog.Internal.State: [sequentialActions] :: Sequential m state -> [Action m state]
+ Hedgehog.Internal.State: concrete :: Var a Concrete -> a
+ Hedgehog.Internal.State: data Parallel m state
+ Hedgehog.Internal.State: data Sequential m state
+ Hedgehog.Internal.State: data Var a v
+ Hedgehog.Internal.State: executeParallel :: (MonadTest m, MonadCatch m, MonadBaseControl IO m, HasCallStack) => (forall v. state v) -> Parallel m state -> m ()
+ Hedgehog.Internal.State: instance (GHC.Classes.Eq a, Data.Functor.Classes.Eq1 v) => GHC.Classes.Eq (Hedgehog.Internal.State.Var a v)
+ Hedgehog.Internal.State: instance (GHC.Classes.Ord a, Data.Functor.Classes.Ord1 v) => GHC.Classes.Ord (Hedgehog.Internal.State.Var a v)
+ Hedgehog.Internal.State: instance (GHC.Show.Show a, Data.Functor.Classes.Show1 v) => GHC.Show.Show (Hedgehog.Internal.State.Var a v)
+ Hedgehog.Internal.State: instance GHC.Classes.Eq Hedgehog.Internal.State.Name
+ Hedgehog.Internal.State: instance GHC.Classes.Ord Hedgehog.Internal.State.Name
+ Hedgehog.Internal.State: instance GHC.Num.Num Hedgehog.Internal.State.Name
+ Hedgehog.Internal.State: instance GHC.Show.Show (Hedgehog.Internal.State.Parallel m state)
+ Hedgehog.Internal.State: instance GHC.Show.Show (Hedgehog.Internal.State.Sequential m state)
+ Hedgehog.Internal.State: instance GHC.Show.Show Hedgehog.Internal.State.Name
+ Hedgehog.Internal.State: instance Hedgehog.Internal.HTraversable.HTraversable (Hedgehog.Internal.State.Var a)
+ Hedgehog.Internal.State: newtype Name
+ Hedgehog.Internal.State: opaque :: Var (Opaque a) Concrete -> a
+ Hedgehog.Internal.State: parallel :: (MonadGen n, MonadTest m) => Range Int -> Range Int -> (forall v. state v) -> [Command n m state] -> n (Parallel m state)
+ Hedgehog.Internal.State: sequential :: (MonadGen n, MonadTest m) => Range Int -> (forall v. state v) -> [Command n m state] -> n (Sequential m state)
- Hedgehog: (===) :: (Monad m, Eq a, Show a, HasCallStack) => a -> a -> Test m ()
+ Hedgehog: (===) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m ()
- Hedgehog: Command :: (state Symbolic -> Maybe (Gen n (input Symbolic))) -> (input Concrete -> Test m output) -> [Callback input output m state] -> Command n m
+ Hedgehog: Command :: (state Symbolic -> Maybe (n (input Symbolic))) -> (input Concrete -> m output) -> [Callback input output state] -> Command n m
- Hedgehog: Ensure :: (state Concrete -> input Concrete -> output -> Test m ()) -> Callback input output m state
+ Hedgehog: Ensure :: (state Concrete -> state Concrete -> input Concrete -> output -> Test ()) -> Callback input output state
- Hedgehog: Require :: (state Symbolic -> input Symbolic -> Bool) -> Callback input output m state
+ Hedgehog: Require :: (state Symbolic -> input Symbolic -> Bool) -> Callback input output state
- Hedgehog: Update :: (forall v. Ord1 v => state v -> input v -> v output -> state v) -> Callback input output m state
+ Hedgehog: Update :: (forall v. Ord1 v => state v -> input v -> Var output v -> state v) -> Callback input output state
- Hedgehog: [commandCallbacks] :: Command n m -> [Callback input output m state]
+ Hedgehog: [commandCallbacks] :: Command n m -> [Callback input output state]
- Hedgehog: [commandExecute] :: Command n m -> input Concrete -> Test m output
+ Hedgehog: [commandExecute] :: Command n m -> input Concrete -> m output
- Hedgehog: [commandGen] :: Command n m -> state Symbolic -> Maybe (Gen n (input Symbolic))
+ Hedgehog: [commandGen] :: Command n m -> state Symbolic -> Maybe (n (input Symbolic))
- Hedgehog: annotate :: (Monad m, HasCallStack) => String -> Test m ()
+ Hedgehog: annotate :: (MonadTest m, HasCallStack) => String -> m ()
- Hedgehog: annotateShow :: (Monad m, Show a, HasCallStack) => a -> Test m ()
+ Hedgehog: annotateShow :: (MonadTest m, Show a, HasCallStack) => a -> m ()
- Hedgehog: assert :: (Monad m, HasCallStack) => Bool -> Test m ()
+ Hedgehog: assert :: (MonadTest m, HasCallStack) => Bool -> m ()
- Hedgehog: data Callback input output m state
+ Hedgehog: data Callback input output state
- Hedgehog: data Var
+ Hedgehog: data Var a v
- Hedgehog: discard :: Monad m => Test m a
+ Hedgehog: discard :: Monad m => PropertyT m a
- Hedgehog: executeSequential :: forall m state. (HasCallStack, MonadCatch m) => (forall v. state v) -> [Action m state] -> Test m ()
+ Hedgehog: executeSequential :: (MonadTest m, MonadCatch m, HasCallStack) => (forall v. state v) -> Sequential m state -> m ()
- Hedgehog: failure :: (Monad m, HasCallStack) => Test m a
+ Hedgehog: failure :: (MonadTest m, HasCallStack) => m a
- Hedgehog: footnote :: Monad m => String -> Test m ()
+ Hedgehog: footnote :: MonadTest m => String -> m ()
- Hedgehog: footnoteShow :: (Monad m, Show a) => a -> Test m ()
+ Hedgehog: footnoteShow :: (MonadTest m, Show a) => a -> m ()
- Hedgehog: forAll :: (Monad m, Show a, HasCallStack) => Gen m a -> Test m a
+ Hedgehog: forAll :: (Monad m, Show a, HasCallStack) => Gen a -> PropertyT m a
- Hedgehog: forAllWith :: (Monad m, HasCallStack) => (a -> String) -> Gen m a -> Test m a
+ Hedgehog: forAllWith :: (Monad m, HasCallStack) => (a -> String) -> Gen a -> PropertyT m a
- Hedgehog: property :: Test IO () -> Property
+ Hedgehog: property :: HasCallStack => PropertyT IO () -> Property
- Hedgehog: success :: Monad m => Test m ()
+ Hedgehog: success :: MonadTest m => m ()
- Hedgehog: tripping :: HasCallStack => Applicative f => Monad m => Show b => Show (f a) => Eq (f a) => a -> (a -> b) -> (b -> f a) -> Test m ()
+ Hedgehog: tripping :: (MonadTest m, Applicative f, Show b, Show (f a), Eq (f a), HasCallStack) => a -> (a -> b) -> (b -> f a) -> m ()
- Hedgehog.Gen: alpha :: Monad m => Gen m Char
+ Hedgehog.Gen: alpha :: MonadGen m => m Char
- Hedgehog.Gen: alphaNum :: Monad m => Gen m Char
+ Hedgehog.Gen: alphaNum :: MonadGen m => m Char
- Hedgehog.Gen: ascii :: Monad m => Gen m Char
+ Hedgehog.Gen: ascii :: MonadGen m => m Char
- Hedgehog.Gen: binit :: Monad m => Gen m Char
+ Hedgehog.Gen: binit :: MonadGen m => m Char
- Hedgehog.Gen: bool :: Monad m => Gen m Bool
+ Hedgehog.Gen: bool :: MonadGen m => m Bool
- Hedgehog.Gen: bool_ :: Monad m => Gen m Bool
+ Hedgehog.Gen: bool_ :: MonadGen m => m Bool
- Hedgehog.Gen: bytes :: Monad m => Range Int -> Gen m ByteString
+ Hedgehog.Gen: bytes :: MonadGen m => Range Int -> m ByteString
- Hedgehog.Gen: choice :: Monad m => [Gen m a] -> Gen m a
+ Hedgehog.Gen: choice :: MonadGen m => [m a] -> m a
- Hedgehog.Gen: constant :: Monad m => a -> Gen m a
+ Hedgehog.Gen: constant :: MonadGen m => a -> m a
- Hedgehog.Gen: digit :: Monad m => Gen m Char
+ Hedgehog.Gen: digit :: MonadGen m => m Char
- Hedgehog.Gen: discard :: Monad m => Gen m a
+ Hedgehog.Gen: discard :: MonadGen m => m a
- Hedgehog.Gen: double :: Monad m => Range Double -> Gen m Double
+ Hedgehog.Gen: double :: MonadGen m => Range Double -> m Double
- Hedgehog.Gen: element :: Monad m => [a] -> Gen m a
+ Hedgehog.Gen: element :: MonadGen m => [a] -> m a
- Hedgehog.Gen: enum :: (Monad m, Enum a) => a -> a -> Gen m a
+ Hedgehog.Gen: enum :: (MonadGen m, Enum a) => a -> a -> m a
- Hedgehog.Gen: enumBounded :: (Monad m, Enum a, Bounded a) => Gen m a
+ Hedgehog.Gen: enumBounded :: (MonadGen m, Enum a, Bounded a) => m a
- Hedgehog.Gen: filter :: Monad m => (a -> Bool) -> Gen m a -> Gen m a
+ Hedgehog.Gen: filter :: MonadGen m => (a -> Bool) -> m a -> m a
- Hedgehog.Gen: float :: Monad m => Range Float -> Gen m Float
+ Hedgehog.Gen: float :: MonadGen m => Range Float -> m Float
- Hedgehog.Gen: frequency :: Monad m => [(Int, Gen m a)] -> Gen m a
+ Hedgehog.Gen: frequency :: MonadGen m => [(Int, m a)] -> m a
- Hedgehog.Gen: hexit :: Monad m => Gen m Char
+ Hedgehog.Gen: hexit :: MonadGen m => m Char
- Hedgehog.Gen: int :: Monad m => Range Int -> Gen m Int
+ Hedgehog.Gen: int :: MonadGen m => Range Int -> m Int
- Hedgehog.Gen: int16 :: Monad m => Range Int16 -> Gen m Int16
+ Hedgehog.Gen: int16 :: MonadGen m => Range Int16 -> m Int16
- Hedgehog.Gen: int32 :: Monad m => Range Int32 -> Gen m Int32
+ Hedgehog.Gen: int32 :: MonadGen m => Range Int32 -> m Int32
- Hedgehog.Gen: int64 :: Monad m => Range Int64 -> Gen m Int64
+ Hedgehog.Gen: int64 :: MonadGen m => Range Int64 -> m Int64
- Hedgehog.Gen: int8 :: Monad m => Range Int8 -> Gen m Int8
+ Hedgehog.Gen: int8 :: MonadGen m => Range Int8 -> m Int8
- Hedgehog.Gen: integral :: (Monad m, Integral a) => Range a -> Gen m a
+ Hedgehog.Gen: integral :: (MonadGen m, Integral a) => Range a -> m a
- Hedgehog.Gen: integral_ :: (Monad m, Integral a) => Range a -> Gen m a
+ Hedgehog.Gen: integral_ :: (MonadGen m, Integral a) => Range a -> m a
- Hedgehog.Gen: just :: Monad m => Gen m (Maybe a) -> Gen m a
+ Hedgehog.Gen: just :: MonadGen m => m (Maybe a) -> m a
- Hedgehog.Gen: latin1 :: Monad m => Gen m Char
+ Hedgehog.Gen: latin1 :: MonadGen m => m Char
- Hedgehog.Gen: list :: Monad m => Range Int -> Gen m a -> Gen m [a]
+ Hedgehog.Gen: list :: MonadGen m => Range Int -> m a -> m [a]
- Hedgehog.Gen: lower :: Monad m => Gen m Char
+ Hedgehog.Gen: lower :: MonadGen m => m Char
- Hedgehog.Gen: map :: (Monad m, Ord k) => Range Int -> Gen m (k, v) -> Gen m (Map k v)
+ Hedgehog.Gen: map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v)
- Hedgehog.Gen: maybe :: Monad m => Gen m a -> Gen m (Maybe a)
+ Hedgehog.Gen: maybe :: MonadGen m => m a -> m (Maybe a)
- Hedgehog.Gen: nonEmpty :: Monad m => Range Int -> Gen m a -> Gen m (NonEmpty a)
+ Hedgehog.Gen: nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a)
- Hedgehog.Gen: octit :: Monad m => Gen m Char
+ Hedgehog.Gen: octit :: MonadGen m => m Char
- Hedgehog.Gen: print :: (MonadIO m, Show a) => Gen m a -> m ()
+ Hedgehog.Gen: print :: (MonadIO m, Show a) => Gen a -> m ()
- Hedgehog.Gen: printTree :: (MonadIO m, Show a) => Gen m a -> m ()
+ Hedgehog.Gen: printTree :: (MonadIO m, Show a) => Gen a -> m ()
- Hedgehog.Gen: printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen m a -> m ()
+ Hedgehog.Gen: printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()
- Hedgehog.Gen: printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen m a -> m ()
+ Hedgehog.Gen: printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()
- Hedgehog.Gen: prune :: Monad m => Gen m a -> Gen m a
+ Hedgehog.Gen: prune :: MonadGen m => m a -> m a
- Hedgehog.Gen: realFloat :: (Monad m, RealFloat a) => Range a -> Gen m a
+ Hedgehog.Gen: realFloat :: (MonadGen m, RealFloat a) => Range a -> m a
- Hedgehog.Gen: realFrac_ :: (Monad m, RealFrac a) => Range a -> Gen m a
+ Hedgehog.Gen: realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a
- Hedgehog.Gen: recursive :: ([Gen m a] -> Gen m a) -> [Gen m a] -> [Gen m a] -> Gen m a
+ Hedgehog.Gen: recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a
- Hedgehog.Gen: resize :: Size -> Gen m a -> Gen m a
+ Hedgehog.Gen: resize :: MonadGen m => Size -> m a -> m a
- Hedgehog.Gen: sample :: MonadIO m => Gen m a -> m [a]
+ Hedgehog.Gen: sample :: MonadIO m => Gen a -> m a
- Hedgehog.Gen: scale :: (Size -> Size) -> Gen m a -> Gen m a
+ Hedgehog.Gen: scale :: MonadGen m => (Size -> Size) -> m a -> m a
- Hedgehog.Gen: seq :: Monad m => Range Int -> Gen m a -> Gen m (Seq a)
+ Hedgehog.Gen: seq :: MonadGen m => Range Int -> m a -> m (Seq a)
- Hedgehog.Gen: set :: (Monad m, Ord a) => Range Int -> Gen m a -> Gen m (Set a)
+ Hedgehog.Gen: set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a)
- Hedgehog.Gen: shrink :: Monad m => (a -> [a]) -> Gen m a -> Gen m a
+ Hedgehog.Gen: shrink :: MonadGen m => (a -> [a]) -> m a -> m a
- Hedgehog.Gen: shuffle :: Monad m => [a] -> Gen m [a]
+ Hedgehog.Gen: shuffle :: MonadGen m => [a] -> m [a]
- Hedgehog.Gen: sized :: (Size -> Gen m a) -> Gen m a
+ Hedgehog.Gen: sized :: MonadGen m => (Size -> m a) -> m a
- Hedgehog.Gen: small :: Gen m a -> Gen m a
+ Hedgehog.Gen: small :: MonadGen m => m a -> m a
- Hedgehog.Gen: string :: Monad m => Range Int -> Gen m Char -> Gen m String
+ Hedgehog.Gen: string :: MonadGen m => Range Int -> m Char -> m String
- Hedgehog.Gen: subsequence :: Monad m => [a] -> Gen m [a]
+ Hedgehog.Gen: subsequence :: MonadGen m => [a] -> m [a]
- Hedgehog.Gen: subterm :: Monad m => Gen m a -> (a -> a) -> Gen m a
+ Hedgehog.Gen: subterm :: MonadGen m => m a -> (a -> a) -> m a
- Hedgehog.Gen: subterm2 :: Monad m => Gen m a -> Gen m a -> (a -> a -> a) -> Gen m a
+ Hedgehog.Gen: subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a
- Hedgehog.Gen: subterm3 :: Monad m => Gen m a -> Gen m a -> Gen m a -> (a -> a -> a -> a) -> Gen m a
+ Hedgehog.Gen: subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a
- Hedgehog.Gen: subtermM :: Monad m => Gen m a -> (a -> Gen m a) -> Gen m a
+ Hedgehog.Gen: subtermM :: MonadGen m => m a -> (a -> m a) -> m a
- Hedgehog.Gen: subtermM2 :: Monad m => Gen m a -> Gen m a -> (a -> a -> Gen m a) -> Gen m a
+ Hedgehog.Gen: subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a
- Hedgehog.Gen: subtermM3 :: Monad m => Gen m a -> Gen m a -> Gen m a -> (a -> a -> a -> Gen m a) -> Gen m a
+ Hedgehog.Gen: subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a
- Hedgehog.Gen: text :: Monad m => Range Int -> Gen m Char -> Gen m Text
+ Hedgehog.Gen: text :: MonadGen m => Range Int -> m Char -> m Text
- Hedgehog.Gen: unicode :: Monad m => Gen m Char
+ Hedgehog.Gen: unicode :: MonadGen m => m Char
- Hedgehog.Gen: unicodeAll :: Monad m => Gen m Char
+ Hedgehog.Gen: unicodeAll :: MonadGen m => m Char
- Hedgehog.Gen: upper :: Monad m => Gen m Char
+ Hedgehog.Gen: upper :: MonadGen m => m Char
- Hedgehog.Gen: utf8 :: Monad m => Range Int -> Gen m Char -> Gen m ByteString
+ Hedgehog.Gen: utf8 :: MonadGen m => Range Int -> m Char -> m ByteString
- Hedgehog.Gen: word :: Monad m => Range Word -> Gen m Word
+ Hedgehog.Gen: word :: MonadGen m => Range Word -> m Word
- Hedgehog.Gen: word16 :: Monad m => Range Word16 -> Gen m Word16
+ Hedgehog.Gen: word16 :: MonadGen m => Range Word16 -> m Word16
- Hedgehog.Gen: word32 :: Monad m => Range Word32 -> Gen m Word32
+ Hedgehog.Gen: word32 :: MonadGen m => Range Word32 -> m Word32
- Hedgehog.Gen: word64 :: Monad m => Range Word64 -> Gen m Word64
+ Hedgehog.Gen: word64 :: MonadGen m => Range Word64 -> m Word64
- Hedgehog.Gen: word8 :: Monad m => Range Word8 -> Gen m Word8
+ Hedgehog.Gen: word8 :: MonadGen m => Range Word8 -> m Word8
- Hedgehog.Internal.Exception: tryAll :: MonadCatch m => m a -> m (Either TypedException a)
+ Hedgehog.Internal.Exception: tryAll :: MonadCatch m => m a -> m (Either SomeException a)
- Hedgehog.Internal.Gen: [unGen] :: Gen m a -> Size -> Seed -> Tree (MaybeT m) a
+ Hedgehog.Internal.Gen: [unGen] :: GenT m a -> Size -> Seed -> Tree (MaybeT m) a
- Hedgehog.Internal.Gen: alpha :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: alpha :: MonadGen m => m Char
- Hedgehog.Internal.Gen: alphaNum :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: alphaNum :: MonadGen m => m Char
- Hedgehog.Internal.Gen: ascii :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: ascii :: MonadGen m => m Char
- Hedgehog.Internal.Gen: binit :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: binit :: MonadGen m => m Char
- Hedgehog.Internal.Gen: bool :: Monad m => Gen m Bool
+ Hedgehog.Internal.Gen: bool :: MonadGen m => m Bool
- Hedgehog.Internal.Gen: bool_ :: Monad m => Gen m Bool
+ Hedgehog.Internal.Gen: bool_ :: MonadGen m => m Bool
- Hedgehog.Internal.Gen: bytes :: Monad m => Range Int -> Gen m ByteString
+ Hedgehog.Internal.Gen: bytes :: MonadGen m => Range Int -> m ByteString
- Hedgehog.Internal.Gen: choice :: Monad m => [Gen m a] -> Gen m a
+ Hedgehog.Internal.Gen: choice :: MonadGen m => [m a] -> m a
- Hedgehog.Internal.Gen: constant :: Monad m => a -> Gen m a
+ Hedgehog.Internal.Gen: constant :: MonadGen m => a -> m a
- Hedgehog.Internal.Gen: digit :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: digit :: MonadGen m => m Char
- Hedgehog.Internal.Gen: discard :: Monad m => Gen m a
+ Hedgehog.Internal.Gen: discard :: MonadGen m => m a
- Hedgehog.Internal.Gen: double :: Monad m => Range Double -> Gen m Double
+ Hedgehog.Internal.Gen: double :: MonadGen m => Range Double -> m Double
- Hedgehog.Internal.Gen: element :: Monad m => [a] -> Gen m a
+ Hedgehog.Internal.Gen: element :: MonadGen m => [a] -> m a
- Hedgehog.Internal.Gen: enum :: (Monad m, Enum a) => a -> a -> Gen m a
+ Hedgehog.Internal.Gen: enum :: (MonadGen m, Enum a) => a -> a -> m a
- Hedgehog.Internal.Gen: enumBounded :: (Monad m, Enum a, Bounded a) => Gen m a
+ Hedgehog.Internal.Gen: enumBounded :: (MonadGen m, Enum a, Bounded a) => m a
- Hedgehog.Internal.Gen: filter :: Monad m => (a -> Bool) -> Gen m a -> Gen m a
+ Hedgehog.Internal.Gen: filter :: MonadGen m => (a -> Bool) -> m a -> m a
- Hedgehog.Internal.Gen: float :: Monad m => Range Float -> Gen m Float
+ Hedgehog.Internal.Gen: float :: MonadGen m => Range Float -> m Float
- Hedgehog.Internal.Gen: freeze :: Monad m => Gen m a -> Gen m (a, Gen m a)
+ Hedgehog.Internal.Gen: freeze :: MonadGen m => m a -> m (a, m a)
- Hedgehog.Internal.Gen: frequency :: Monad m => [(Int, Gen m a)] -> Gen m a
+ Hedgehog.Internal.Gen: frequency :: MonadGen m => [(Int, m a)] -> m a
- Hedgehog.Internal.Gen: generate :: Monad m => (Size -> Seed -> a) -> Gen m a
+ Hedgehog.Internal.Gen: generate :: MonadGen m => (Size -> Seed -> a) -> m a
- Hedgehog.Internal.Gen: hexit :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: hexit :: MonadGen m => m Char
- Hedgehog.Internal.Gen: int :: Monad m => Range Int -> Gen m Int
+ Hedgehog.Internal.Gen: int :: MonadGen m => Range Int -> m Int
- Hedgehog.Internal.Gen: int16 :: Monad m => Range Int16 -> Gen m Int16
+ Hedgehog.Internal.Gen: int16 :: MonadGen m => Range Int16 -> m Int16
- Hedgehog.Internal.Gen: int32 :: Monad m => Range Int32 -> Gen m Int32
+ Hedgehog.Internal.Gen: int32 :: MonadGen m => Range Int32 -> m Int32
- Hedgehog.Internal.Gen: int64 :: Monad m => Range Int64 -> Gen m Int64
+ Hedgehog.Internal.Gen: int64 :: MonadGen m => Range Int64 -> m Int64
- Hedgehog.Internal.Gen: int8 :: Monad m => Range Int8 -> Gen m Int8
+ Hedgehog.Internal.Gen: int8 :: MonadGen m => Range Int8 -> m Int8
- Hedgehog.Internal.Gen: integral :: (Monad m, Integral a) => Range a -> Gen m a
+ Hedgehog.Internal.Gen: integral :: (MonadGen m, Integral a) => Range a -> m a
- Hedgehog.Internal.Gen: integral_ :: (Monad m, Integral a) => Range a -> Gen m a
+ Hedgehog.Internal.Gen: integral_ :: (MonadGen m, Integral a) => Range a -> m a
- Hedgehog.Internal.Gen: just :: Monad m => Gen m (Maybe a) -> Gen m a
+ Hedgehog.Internal.Gen: just :: MonadGen m => m (Maybe a) -> m a
- Hedgehog.Internal.Gen: latin1 :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: latin1 :: MonadGen m => m Char
- Hedgehog.Internal.Gen: liftTree :: Tree (MaybeT m) a -> Gen m a
+ Hedgehog.Internal.Gen: liftTree :: Tree (MaybeT m) a -> GenT m a
- Hedgehog.Internal.Gen: list :: Monad m => Range Int -> Gen m a -> Gen m [a]
+ Hedgehog.Internal.Gen: list :: MonadGen m => Range Int -> m a -> m [a]
- Hedgehog.Internal.Gen: lower :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: lower :: MonadGen m => m Char
- Hedgehog.Internal.Gen: map :: (Monad m, Ord k) => Range Int -> Gen m (k, v) -> Gen m (Map k v)
+ Hedgehog.Internal.Gen: map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v)
- Hedgehog.Internal.Gen: maybe :: Monad m => Gen m a -> Gen m (Maybe a)
+ Hedgehog.Internal.Gen: maybe :: MonadGen m => m a -> m (Maybe a)
- Hedgehog.Internal.Gen: nonEmpty :: Monad m => Range Int -> Gen m a -> Gen m (NonEmpty a)
+ Hedgehog.Internal.Gen: nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a)
- Hedgehog.Internal.Gen: octit :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: octit :: MonadGen m => m Char
- Hedgehog.Internal.Gen: print :: (MonadIO m, Show a) => Gen m a -> m ()
+ Hedgehog.Internal.Gen: print :: (MonadIO m, Show a) => Gen a -> m ()
- Hedgehog.Internal.Gen: printTree :: (MonadIO m, Show a) => Gen m a -> m ()
+ Hedgehog.Internal.Gen: printTree :: (MonadIO m, Show a) => Gen a -> m ()
- Hedgehog.Internal.Gen: printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen m a -> m ()
+ Hedgehog.Internal.Gen: printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()
- Hedgehog.Internal.Gen: printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen m a -> m ()
+ Hedgehog.Internal.Gen: printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()
- Hedgehog.Internal.Gen: prune :: Monad m => Gen m a -> Gen m a
+ Hedgehog.Internal.Gen: prune :: MonadGen m => m a -> m a
- Hedgehog.Internal.Gen: realFloat :: (Monad m, RealFloat a) => Range a -> Gen m a
+ Hedgehog.Internal.Gen: realFloat :: (MonadGen m, RealFloat a) => Range a -> m a
- Hedgehog.Internal.Gen: realFrac_ :: (Monad m, RealFrac a) => Range a -> Gen m a
+ Hedgehog.Internal.Gen: realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a
- Hedgehog.Internal.Gen: recursive :: ([Gen m a] -> Gen m a) -> [Gen m a] -> [Gen m a] -> Gen m a
+ Hedgehog.Internal.Gen: recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a
- Hedgehog.Internal.Gen: renderNodes :: (Monad m, Show a) => Size -> Seed -> Gen m a -> Tree m String
+ Hedgehog.Internal.Gen: renderNodes :: (Monad m, Show a) => Size -> Seed -> Gen a -> Tree m String
- Hedgehog.Internal.Gen: resize :: Size -> Gen m a -> Gen m a
+ Hedgehog.Internal.Gen: resize :: MonadGen m => Size -> m a -> m a
- Hedgehog.Internal.Gen: sample :: MonadIO m => Gen m a -> m [a]
+ Hedgehog.Internal.Gen: sample :: MonadIO m => Gen a -> m a
- Hedgehog.Internal.Gen: scale :: (Size -> Size) -> Gen m a -> Gen m a
+ Hedgehog.Internal.Gen: scale :: MonadGen m => (Size -> Size) -> m a -> m a
- Hedgehog.Internal.Gen: seq :: Monad m => Range Int -> Gen m a -> Gen m (Seq a)
+ Hedgehog.Internal.Gen: seq :: MonadGen m => Range Int -> m a -> m (Seq a)
- Hedgehog.Internal.Gen: set :: (Monad m, Ord a) => Range Int -> Gen m a -> Gen m (Set a)
+ Hedgehog.Internal.Gen: set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a)
- Hedgehog.Internal.Gen: shrink :: Monad m => (a -> [a]) -> Gen m a -> Gen m a
+ Hedgehog.Internal.Gen: shrink :: MonadGen m => (a -> [a]) -> m a -> m a
- Hedgehog.Internal.Gen: shuffle :: Monad m => [a] -> Gen m [a]
+ Hedgehog.Internal.Gen: shuffle :: MonadGen m => [a] -> m [a]
- Hedgehog.Internal.Gen: sized :: (Size -> Gen m a) -> Gen m a
+ Hedgehog.Internal.Gen: sized :: MonadGen m => (Size -> m a) -> m a
- Hedgehog.Internal.Gen: small :: Gen m a -> Gen m a
+ Hedgehog.Internal.Gen: small :: MonadGen m => m a -> m a
- Hedgehog.Internal.Gen: string :: Monad m => Range Int -> Gen m Char -> Gen m String
+ Hedgehog.Internal.Gen: string :: MonadGen m => Range Int -> m Char -> m String
- Hedgehog.Internal.Gen: subsequence :: Monad m => [a] -> Gen m [a]
+ Hedgehog.Internal.Gen: subsequence :: MonadGen m => [a] -> m [a]
- Hedgehog.Internal.Gen: subterm :: Monad m => Gen m a -> (a -> a) -> Gen m a
+ Hedgehog.Internal.Gen: subterm :: MonadGen m => m a -> (a -> a) -> m a
- Hedgehog.Internal.Gen: subterm2 :: Monad m => Gen m a -> Gen m a -> (a -> a -> a) -> Gen m a
+ Hedgehog.Internal.Gen: subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a
- Hedgehog.Internal.Gen: subterm3 :: Monad m => Gen m a -> Gen m a -> Gen m a -> (a -> a -> a -> a) -> Gen m a
+ Hedgehog.Internal.Gen: subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a
- Hedgehog.Internal.Gen: subtermM :: Monad m => Gen m a -> (a -> Gen m a) -> Gen m a
+ Hedgehog.Internal.Gen: subtermM :: MonadGen m => m a -> (a -> m a) -> m a
- Hedgehog.Internal.Gen: subtermM2 :: Monad m => Gen m a -> Gen m a -> (a -> a -> Gen m a) -> Gen m a
+ Hedgehog.Internal.Gen: subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a
- Hedgehog.Internal.Gen: subtermM3 :: Monad m => Gen m a -> Gen m a -> Gen m a -> (a -> a -> a -> Gen m a) -> Gen m a
+ Hedgehog.Internal.Gen: subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a
- Hedgehog.Internal.Gen: subtermMVec :: Monad m => Vec n (Gen m a) -> (Vec n a -> Gen m a) -> Gen m a
+ Hedgehog.Internal.Gen: subtermMVec :: MonadGen m => Vec n (m a) -> (Vec n a -> m a) -> m a
- Hedgehog.Internal.Gen: text :: Monad m => Range Int -> Gen m Char -> Gen m Text
+ Hedgehog.Internal.Gen: text :: MonadGen m => Range Int -> m Char -> m Text
- Hedgehog.Internal.Gen: unicode :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: unicode :: MonadGen m => m Char
- Hedgehog.Internal.Gen: unicodeAll :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: unicodeAll :: MonadGen m => m Char
- Hedgehog.Internal.Gen: upper :: Monad m => Gen m Char
+ Hedgehog.Internal.Gen: upper :: MonadGen m => m Char
- Hedgehog.Internal.Gen: utf8 :: Monad m => Range Int -> Gen m Char -> Gen m ByteString
+ Hedgehog.Internal.Gen: utf8 :: MonadGen m => Range Int -> m Char -> m ByteString
- Hedgehog.Internal.Gen: word :: Monad m => Range Word -> Gen m Word
+ Hedgehog.Internal.Gen: word :: MonadGen m => Range Word -> m Word
- Hedgehog.Internal.Gen: word16 :: Monad m => Range Word16 -> Gen m Word16
+ Hedgehog.Internal.Gen: word16 :: MonadGen m => Range Word16 -> m Word16
- Hedgehog.Internal.Gen: word32 :: Monad m => Range Word32 -> Gen m Word32
+ Hedgehog.Internal.Gen: word32 :: MonadGen m => Range Word32 -> m Word32
- Hedgehog.Internal.Gen: word64 :: Monad m => Range Word64 -> Gen m Word64
+ Hedgehog.Internal.Gen: word64 :: MonadGen m => Range Word64 -> m Word64
- Hedgehog.Internal.Gen: word8 :: Monad m => Range Word8 -> Gen m Word8
+ Hedgehog.Internal.Gen: word8 :: MonadGen m => Range Word8 -> m Word8
- Hedgehog.Internal.Property: (===) :: (Monad m, Eq a, Show a, HasCallStack) => a -> a -> Test m ()
+ Hedgehog.Internal.Property: (===) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m ()
- Hedgehog.Internal.Property: Property :: !PropertyConfig -> Test IO () -> Property
+ Hedgehog.Internal.Property: Property :: !PropertyConfig -> PropertyT IO () -> Property
- Hedgehog.Internal.Property: PropertyConfig :: !TestLimit -> !DiscardLimit -> !ShrinkLimit -> PropertyConfig
+ Hedgehog.Internal.Property: PropertyConfig :: !TestLimit -> !DiscardLimit -> !ShrinkLimit -> !ShrinkRetries -> PropertyConfig
- Hedgehog.Internal.Property: [propertyTest] :: Property -> Test IO ()
+ Hedgehog.Internal.Property: [propertyTest] :: Property -> PropertyT IO ()
- Hedgehog.Internal.Property: [unTest] :: Test m a -> ExceptT Failure (WriterT [Log] (Gen m)) a
+ Hedgehog.Internal.Property: [unTest] :: TestT m a -> ExceptT Failure (WriterT [Log] m) a
- Hedgehog.Internal.Property: annotate :: (Monad m, HasCallStack) => String -> Test m ()
+ Hedgehog.Internal.Property: annotate :: (MonadTest m, HasCallStack) => String -> m ()
- Hedgehog.Internal.Property: annotateShow :: (Monad m, Show a, HasCallStack) => a -> Test m ()
+ Hedgehog.Internal.Property: annotateShow :: (MonadTest m, Show a, HasCallStack) => a -> m ()
- Hedgehog.Internal.Property: assert :: (Monad m, HasCallStack) => Bool -> Test m ()
+ Hedgehog.Internal.Property: assert :: (MonadTest m, HasCallStack) => Bool -> m ()
- Hedgehog.Internal.Property: discard :: Monad m => Test m a
+ Hedgehog.Internal.Property: discard :: Monad m => PropertyT m a
- Hedgehog.Internal.Property: failWith :: (Monad m, HasCallStack) => Maybe Diff -> String -> Test m a
+ Hedgehog.Internal.Property: failWith :: (MonadTest m, HasCallStack) => Maybe Diff -> String -> m a
- Hedgehog.Internal.Property: failure :: (Monad m, HasCallStack) => Test m a
+ Hedgehog.Internal.Property: failure :: (MonadTest m, HasCallStack) => m a
- Hedgehog.Internal.Property: footnote :: Monad m => String -> Test m ()
+ Hedgehog.Internal.Property: footnote :: MonadTest m => String -> m ()
- Hedgehog.Internal.Property: footnoteShow :: (Monad m, Show a) => a -> Test m ()
+ Hedgehog.Internal.Property: footnoteShow :: (MonadTest m, Show a) => a -> m ()
- Hedgehog.Internal.Property: forAll :: (Monad m, Show a, HasCallStack) => Gen m a -> Test m a
+ Hedgehog.Internal.Property: forAll :: (Monad m, Show a, HasCallStack) => Gen a -> PropertyT m a
- Hedgehog.Internal.Property: forAllWith :: (Monad m, HasCallStack) => (a -> String) -> Gen m a -> Test m a
+ Hedgehog.Internal.Property: forAllWith :: (Monad m, HasCallStack) => (a -> String) -> Gen a -> PropertyT m a
- Hedgehog.Internal.Property: property :: Test IO () -> Property
+ Hedgehog.Internal.Property: property :: HasCallStack => PropertyT IO () -> Property
- Hedgehog.Internal.Property: runTest :: Test m a -> Gen m (Either Failure a, [Log])
+ Hedgehog.Internal.Property: runTest :: Test a -> (Either Failure a, [Log])
- Hedgehog.Internal.Property: success :: Monad m => Test m ()
+ Hedgehog.Internal.Property: success :: MonadTest m => m ()
- Hedgehog.Internal.Property: writeLog :: Monad m => Log -> Test m ()
+ Hedgehog.Internal.Property: writeLog :: MonadTest m => Log -> m ()
- Hedgehog.Internal.Region: Region :: TVar (Maybe ConsoleRegion) -> Region
+ Hedgehog.Internal.Region: Region :: TVar Body -> Region
- Hedgehog.Internal.Region: [unRegion] :: Region -> TVar (Maybe ConsoleRegion)
+ Hedgehog.Internal.Region: [unRegion] :: Region -> TVar Body
- Hedgehog.Internal.Region: moveToBottom :: ConsoleRegion -> STM ()
+ Hedgehog.Internal.Region: moveToBottom :: Region -> STM ()
- Hedgehog.Internal.Runner: checkReport :: forall m. MonadIO m => MonadCatch m => PropertyConfig -> Size -> Seed -> Test m () -> (Report Progress -> m ()) -> m (Report Result)
+ Hedgehog.Internal.Runner: checkReport :: forall m. MonadIO m => MonadCatch m => PropertyConfig -> Size -> Seed -> PropertyT m () -> (Report Progress -> m ()) -> m (Report Result)
- Hedgehog.Internal.State: Action :: input Symbolic -> Symbolic output -> (input Concrete -> Test m output) -> (state Symbolic -> input Symbolic -> Bool) -> (forall v. Ord1 v => state v -> input v -> v output -> state v) -> (state Concrete -> input Concrete -> output -> Test m ()) -> Action m
+ Hedgehog.Internal.State: Action :: input Symbolic -> Symbolic output -> (input Concrete -> m output) -> (state Symbolic -> input Symbolic -> Bool) -> (forall v. Ord1 v => state v -> input v -> Var output v -> state v) -> (state Concrete -> state Concrete -> input Concrete -> output -> Test ()) -> Action m
- Hedgehog.Internal.State: Command :: (state Symbolic -> Maybe (Gen n (input Symbolic))) -> (input Concrete -> Test m output) -> [Callback input output m state] -> Command n m
+ Hedgehog.Internal.State: Command :: (state Symbolic -> Maybe (n (input Symbolic))) -> (input Concrete -> m output) -> [Callback input output state] -> Command n m
- Hedgehog.Internal.State: Ensure :: (state Concrete -> input Concrete -> output -> Test m ()) -> Callback input output m state
+ Hedgehog.Internal.State: Ensure :: (state Concrete -> state Concrete -> input Concrete -> output -> Test ()) -> Callback input output state
- Hedgehog.Internal.State: Environment :: Map Var Dynamic -> Environment
+ Hedgehog.Internal.State: Environment :: Map Name Dynamic -> Environment
- Hedgehog.Internal.State: EnvironmentValueNotFound :: !Var -> EnvironmentError
+ Hedgehog.Internal.State: EnvironmentValueNotFound :: !Name -> EnvironmentError
- Hedgehog.Internal.State: Require :: (state Symbolic -> input Symbolic -> Bool) -> Callback input output m state
+ Hedgehog.Internal.State: Require :: (state Symbolic -> input Symbolic -> Bool) -> Callback input output state
- Hedgehog.Internal.State: Update :: (forall v. Ord1 v => state v -> input v -> v output -> state v) -> Callback input output m state
+ Hedgehog.Internal.State: Update :: (forall v. Ord1 v => state v -> input v -> Var output v -> state v) -> Callback input output state
- Hedgehog.Internal.State: Var :: Int -> Var
+ Hedgehog.Internal.State: Var :: (v a) -> Var a v
- Hedgehog.Internal.State: [Symbolic] :: Typeable a => Var -> Symbolic a
+ Hedgehog.Internal.State: [Symbolic] :: Typeable a => Name -> Symbolic a
- Hedgehog.Internal.State: [actionEnsure] :: Action m -> state Concrete -> input Concrete -> output -> Test m ()
+ Hedgehog.Internal.State: [actionEnsure] :: Action m -> state Concrete -> state Concrete -> input Concrete -> output -> Test ()
- Hedgehog.Internal.State: [actionExecute] :: Action m -> input Concrete -> Test m output
+ Hedgehog.Internal.State: [actionExecute] :: Action m -> input Concrete -> m output
- Hedgehog.Internal.State: [actionUpdate] :: Action m -> forall v. Ord1 v => state v -> input v -> v output -> state v
+ Hedgehog.Internal.State: [actionUpdate] :: Action m -> forall v. Ord1 v => state v -> input v -> Var output v -> state v
- Hedgehog.Internal.State: [commandCallbacks] :: Command n m -> [Callback input output m state]
+ Hedgehog.Internal.State: [commandCallbacks] :: Command n m -> [Callback input output state]
- Hedgehog.Internal.State: [commandExecute] :: Command n m -> input Concrete -> Test m output
+ Hedgehog.Internal.State: [commandExecute] :: Command n m -> input Concrete -> m output
- Hedgehog.Internal.State: [commandGen] :: Command n m -> state Symbolic -> Maybe (Gen n (input Symbolic))
+ Hedgehog.Internal.State: [commandGen] :: Command n m -> state Symbolic -> Maybe (n (input Symbolic))
- Hedgehog.Internal.State: [unEnvironment] :: Environment -> Map Var Dynamic
+ Hedgehog.Internal.State: [unEnvironment] :: Environment -> Map Name Dynamic
- Hedgehog.Internal.State: action :: (Monad n, Monad m) => [Command n m state] -> Gen (StateT (state Symbolic, Var) n) (Action m state)
+ Hedgehog.Internal.State: action :: (MonadGen n, MonadTest m) => [Command n m state] -> StateT (Context state) n (Action m state)
- Hedgehog.Internal.State: data Callback input output m state
+ Hedgehog.Internal.State: data Callback input output state
- Hedgehog.Internal.State: dropInvalid :: (forall v. state v) -> [Action m state] -> [Action m state]
+ Hedgehog.Internal.State: dropInvalid :: [Action m state] -> State (Context state) [Action m state]
- Hedgehog.Internal.State: executeSequential :: forall m state. (HasCallStack, MonadCatch m) => (forall v. state v) -> [Action m state] -> Test m ()
+ Hedgehog.Internal.State: executeSequential :: (MonadTest m, MonadCatch m, HasCallStack) => (forall v. state v) -> Sequential m state -> m ()
- Hedgehog.Internal.State: takeVariables :: forall t. HTraversable t => t Symbolic -> Map Var TypeRep
+ Hedgehog.Internal.State: takeVariables :: forall t. HTraversable t => t Symbolic -> Map Name TypeRep
- Hedgehog.Internal.State: variablesOK :: HTraversable t => t Symbolic -> Map Var TypeRep -> Bool
+ Hedgehog.Internal.State: variablesOK :: HTraversable t => t Symbolic -> Map Name TypeRep -> Bool
- Hedgehog.Internal.Tripping: tripping :: HasCallStack => Applicative f => Monad m => Show b => Show (f a) => Eq (f a) => a -> (a -> b) -> (b -> f a) -> Test m ()
+ Hedgehog.Internal.Tripping: tripping :: (MonadTest m, Applicative f, Show b, Show (f a), Eq (f a), HasCallStack) => a -> (a -> b) -> (b -> f a) -> m ()

Files

CHANGELOG.md view
@@ -1,38 +1,93 @@+## Version 0.5 (2017-07-16)++- Parallel state machine testing, allows detection of commands which are not-atomic ([#98][98], [@jystic][jystic])+- Easier to use variables for state machine testing ([#94][94], [@jystic][jystic])+- `MonadGen` class allows the use of transformers like `ReaderT` and `StateT` on the outside of generators ([#99][99], [@jystic][jystic])+- Better error messages for tests which throw exceptions ([#95][95], [@jystic][jystic])+- Separated test input generation and assertions in to `PropertyT` and `TestT` respectively, this allows `TestT` to have a `MonadBaseControl` instance ([#96][96], [@jystic][jystic])+- This document grew links to the pull requests which introduced various changes ([#93][93], [@moodmosaic][moodmosaic])+ ## Version 0.4.1 (2017-06-28) -- Fixed runtime type error that could occur when shrinking state machine commands (#91, @jystic)+- Fixed runtime type error that could occur when shrinking state machine commands ([#91][91], [@jystic][jystic])  ## Version 0.4 (2017-06-28) -- Abstract state machine testing, check out the [process registry example](https://github.com/hedgehogqa/haskell-hedgehog/blob/master/hedgehog-example/test/Test/Example/Registry.hs) to see how it works (#89, @jystic)-- `liftCatch`, `liftCatchIO`, `withCatch` functions for isolating exceptions during tests (#89, @jystic)+- Abstract state machine testing, check out the Tim Humphries' great [blog post](http://teh.id.au/posts/2017/07/15/state-machine-testing) or the [process registry example](https://github.com/hedgehogqa/haskell-hedgehog/blob/master/hedgehog-example/test/Test/Example/Registry.hs) to see how it works ([#89][89], [@jystic][jystic])+- `liftCatch`, `liftCatchIO`, `withCatch` functions for isolating exceptions during tests ([#89][89], [@jystic][jystic])  ## Version 0.3 (2017-06-11) -- Exponential range combinators (#43, @chris-martin)-- Roundtrip example, check out the [blog post](http://teh.id.au/posts/2017/06/07/round-trip-property/) (#85, @thumphries)-- `tripping` now displays intermediate value (#85, @jystic)-- `distribute` function for pulling a transformer out to the top level (#83, @jystic)-- `withExceptT` function for executing tests with an inner `ExceptT` (e.g. `Test (ExceptT x m) a`) (#83, @jystic)+- Exponential range combinators ([#43][43], [@chris-martin][chris-martin])+- Roundtrip example, check out the [blog post](http://teh.id.au/posts/2017/06/07/round-trip-property/) ([#85][85], [@thumphries][thumphries])+- `tripping` now displays intermediate value ([#85][85], [@jystic][jystic])+- `distribute` function for pulling a transformer out to the top level ([#83][83], [@jystic][jystic])+- `withExceptT` function for executing tests with an inner `ExceptT` (e.g. `Test (ExceptT x m) a`) ([#83][83], [@jystic][jystic])  ## Version 0.2.2 (2017-05-16) -- Fixed scope of `unicode` character generators (#76, @moodmosaic)-- Widen version bounds for some dependencies (#80, @amarpotghan)-- Expose test modules to fix build on nix / hydra (#78, @amarpotghan)-- Fixes for GHC 8.2 RC2 (#77, @erikd)+- Fixed scope of `unicode` character generators ([#76][76], [@moodmosaic][moodmosaic])+- Widen version bounds for some dependencies ([#80][80], [@amarpotghan][amarpotghan])+- Expose test modules to fix build on nix / hydra ([#78][78], [@amarpotghan][amarpotghan])+- Fixes for GHC 8.2 RC2 ([#77][77], [@erikd][erikd])  ## Version 0.2.1 (2017-05-09) -- Added `ascii`, `latin1`, `unicode` character generators (#73, @jystic)+- Added `ascii`, `latin1`, `unicode` character generators ([#73][73], [@jystic][jystic])  ## Version 0.2 (2017-05-06) -- Added a quiet test runner which can be activated by setting `HEDGEHOG_VERBOSITY=0` (@jystic)-- Concurrent test runner does not display tests until they are executing (@jystic)-- Test runner now outputs a summary of how many successful / failed tests were run (@jystic)-- `checkSequential` and `checkParallel` now allow for tests to be run without Template Haskell (@jystic)-- Auto-discovery of properties is now available via `discover` instead of being baked in (@jystic)-- `annotate` allows source code to be annotated inline with extra information (@jystic)-- `forAllWith` can be used to generate values without a `Show` instance (@jystic)-- Removed uses of `Typeable` to allow for generating types which cannot implement it (@jystic)+- Added a quiet test runner which can be activated by setting `HEDGEHOG_VERBOSITY=0` ([@jystic][jystic])+- Concurrent test runner does not display tests until they are executing ([@jystic][jystic])+- Test runner now outputs a summary of how many successful / failed tests were run ([@jystic][jystic])+- `checkSequential` and `checkParallel` now allow for tests to be run without Template Haskell ([@jystic][jystic])+- Auto-discovery of properties is now available via `discover` instead of being baked in ([@jystic][jystic])+- `annotate` allows source code to be annotated inline with extra information ([@jystic][jystic])+- `forAllWith` can be used to generate values without a `Show` instance ([@jystic][jystic])+- Removed uses of `Typeable` to allow for generating types which cannot implement it ([@jystic][jystic])++[jystic]:+  https://github.com/jystic+[chris-martin]:+  https://github.com/chris-martin+[thumphries]:+  https://github.com/thumphries+[moodmosaic]:+  https://github.com/moodmosaic+[amarpotghan]:+  https://github.com/amarpotghan+[erikd]:+  https://github.com/erikd++[99]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/99+[98]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/98+[96]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/96+[95]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/95+[94]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/94+[93]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/93+[91]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/91+[89]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/89+[85]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/85+[83]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/83+[80]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/80+[78]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/78+[77]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/77+[76]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/76+[73]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/73+[43]:+  https://github.com/hedgehogqa/haskell-hedgehog/pull/43
README.md view
@@ -12,6 +12,7 @@ ## Features  - Integrated shrinking, shrinks obey invariants by construction.+- Abstract state machine testing. - Generators allow monadic effects. - Range combinators for full control over the scope of generated numbers and collections. - Equality and roundtrip assertions show a diff instead of the two inequal values.@@ -76,7 +77,7 @@ ```   [hackage]: http://hackage.haskell.org/package/hedgehog- [hackage-shield]: https://img.shields.io/badge/hackage-v0.4.1-blue.svg+ [hackage-shield]: https://img.shields.io/badge/hackage-v0.5-blue.svg   [travis]: https://travis-ci.org/hedgehogqa/haskell-hedgehog  [travis-shield]: https://travis-ci.org/hedgehogqa/haskell-hedgehog.svg?branch=master
hedgehog.cabal view
@@ -1,7 +1,7 @@ name:   hedgehog version:-  0.4.1+  0.5 license:   BSD3 author:@@ -50,11 +50,13 @@     , ansi-terminal                   >= 0.6        && < 0.7     , async                           >= 2.0        && < 2.2     , bytestring                      >= 0.10       && < 0.11-    , concurrent-output               >= 1.7        && < 2.0+    , concurrent-output               >= 1.7        && < 1.11     , containers                      >= 0.4        && < 0.6     , directory                       >= 1.2        && < 1.4     , exceptions                      >= 0.7        && < 0.9+    , lifted-async                    >= 0.7        && < 0.10     , mmorph                          >= 1.0        && < 1.2+    , monad-control                   >= 1.0        && < 1.1     , mtl                             >= 2.1        && < 2.3     , pretty-show                     >= 1.6        && < 1.7     , primitive                       >= 0.6        && < 0.7
src/Hedgehog.hs view
@@ -44,26 +44,20 @@ -- >   ✓ prop_reverse passed 100 tests. -- module Hedgehog (-    Group(..)-  , GroupName-  , Property+  -- * Properties+    Property+  , PropertyT+  , Group(..)   , PropertyName-  , Test-  , TestLimit-  , DiscardLimit-  , ShrinkLimit--  , Gen-  , Range-  , Size(..)-  , Seed(..)+  , GroupName -  -- * Property   , property-  , withTests-  , withDiscards-  , withShrinks+  , test +  , forAll+  , forAllWith+  , discard+   , check   , recheck @@ -71,39 +65,62 @@   , checkParallel   , checkSequential -  -- * Test-  , forAll-  , forAllWith+  , withTests+  , TestLimit++  , withDiscards+  , DiscardLimit++  , withShrinks+  , ShrinkLimit++  , withRetries+  , ShrinkRetries++  -- * Generating Test Data+  , Gen+  , GenT+  , MonadGen(..)++  , Range+  , Size(..)+  , Seed(..)++  -- * Tests+  , Test+  , TestT+  , MonadTest(..)   , annotate   , annotateShow   , footnote   , footnoteShow   , success-  , discard   , failure   , assert   , (===)--  , liftCatch-  , liftCatchIO-  , liftEither-  , liftExceptT--  , withCatch-  , withExceptT-  , withResourceT-   , tripping -  -- * Abstract State Machine+  , eval+  , evalM+  , evalIO+  , evalEither+  , evalExceptT++  -- * State Machine Tests   , Command(..)   , Callback(..)   , Action+  , Sequential(..)+  , Parallel(..)   , executeSequential+  , executeParallel +  , Var(..)+  , concrete+  , opaque++  , Symbolic   , Concrete(..)-  , Symbolic(..)-  , Var   , Opaque(..)    -- * Transformers@@ -125,26 +142,30 @@ import           Data.Functor.Classes (Eq1, eq1, Ord1, compare1, Show1, showsPrec1)  import           Hedgehog.Internal.Distributive (Distributive(..))-import           Hedgehog.Internal.Gen (Gen)+import           Hedgehog.Internal.Gen (Gen, GenT, MonadGen(..)) import           Hedgehog.Internal.HTraversable (HTraversable(..)) import           Hedgehog.Internal.Opaque (Opaque(..)) import           Hedgehog.Internal.Property (annotate, annotateShow) import           Hedgehog.Internal.Property (assert, (===)) import           Hedgehog.Internal.Property (discard, failure, success) import           Hedgehog.Internal.Property (DiscardLimit, withDiscards)+import           Hedgehog.Internal.Property (eval, evalM, evalIO)+import           Hedgehog.Internal.Property (evalEither, evalExceptT) import           Hedgehog.Internal.Property (footnote, footnoteShow) import           Hedgehog.Internal.Property (forAll, forAllWith)-import           Hedgehog.Internal.Property (liftCatch, liftCatchIO, liftEither, liftExceptT)-import           Hedgehog.Internal.Property (Property, PropertyName, Group(..), GroupName)+import           Hedgehog.Internal.Property (MonadTest(..))+import           Hedgehog.Internal.Property (Property, PropertyT, PropertyName)+import           Hedgehog.Internal.Property (Group(..), GroupName) import           Hedgehog.Internal.Property (ShrinkLimit, withShrinks)-import           Hedgehog.Internal.Property (Test, property)+import           Hedgehog.Internal.Property (ShrinkRetries, withRetries)+import           Hedgehog.Internal.Property (Test, TestT, property, test) import           Hedgehog.Internal.Property (TestLimit, withTests)-import           Hedgehog.Internal.Property (withCatch, withExceptT, withResourceT) import           Hedgehog.Internal.Range (Range, Size(..)) import           Hedgehog.Internal.Runner (check, recheck, checkSequential, checkParallel) import           Hedgehog.Internal.Seed (Seed(..))-import           Hedgehog.Internal.State (Command(..), Callback(..), Action)-import           Hedgehog.Internal.State (executeSequential)-import           Hedgehog.Internal.State (Var(..), Symbolic(..), Concrete(..))+import           Hedgehog.Internal.State (Command(..), Callback(..))+import           Hedgehog.Internal.State (Action, Sequential(..), Parallel(..))+import           Hedgehog.Internal.State (executeSequential, executeParallel)+import           Hedgehog.Internal.State (Var(..), Symbolic, Concrete(..), concrete, opaque) import           Hedgehog.Internal.TH (discover) import           Hedgehog.Internal.Tripping (tripping)
src/Hedgehog/Gen.hs view
@@ -1,8 +1,7 @@ module Hedgehog.Gen (-  -- * Transformer-    Gen-   -- * Combinators+    lift+   -- ** Shrinking   , shrink   , prune@@ -82,6 +81,7 @@   , map    -- ** Subterms+  , freeze   , subterm   , subtermM   , subterm2@@ -94,7 +94,8 @@   , shuffle    -- ** Abstract State Machine-  , actions+  , sequential+  , parallel    -- * Sampling Generators   , sample@@ -105,6 +106,6 @@   ) where  import           Hedgehog.Internal.Gen-import           Hedgehog.Internal.State (actions)+import           Hedgehog.Internal.State (sequential, parallel)  import           Prelude hiding (filter, print, maybe, map, seq)
src/Hedgehog/Internal/Exception.hs view
@@ -1,42 +1,23 @@ module Hedgehog.Internal.Exception (-    TypedException(..)-  , tryAll+    tryAll+  , tryEvaluate   ) where -import           Control.Exception (Exception(..), AsyncException, SomeException(..))+import           Control.Exception (Exception(..), AsyncException, SomeException(..), evaluate) import           Control.Monad.Catch (MonadCatch(..), throwM) -import           Data.Typeable (typeOf)+import           System.IO.Unsafe (unsafePerformIO)  --- | Newtype for 'SomeException' with a 'Show' instance that only contains---   valid Haskell 98 tokens and also includes the type of the exception.------   For example, when catching the exception thrown by @fail "foo" :: IO ()@---   and calling show:------ @---   IOException "user error (foo)"--- @------   Having access to the type can be useful when trying to track down the---   source of an exception.----newtype TypedException =-  TypedException SomeException--instance Show TypedException where-  showsPrec p (TypedException (SomeException x)) =-    showParen (p > 10) $-      showsPrec 11 (typeOf x) .-      showChar ' ' .-      showsPrec 11 (displayException x)--tryAll :: MonadCatch m => m a -> m (Either TypedException a)+tryAll :: MonadCatch m => m a -> m (Either SomeException a) tryAll m =   catch (fmap Right m) $ \exception ->     case fromException exception :: Maybe AsyncException of       Nothing ->-        pure . Left $ TypedException exception+        pure $ Left exception       Just async ->         throwM async++tryEvaluate :: a -> Either SomeException a+tryEvaluate x =+  unsafePerformIO (tryAll (evaluate x))
src/Hedgehog/Internal/Gen.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -15,9 +17,13 @@ {-# LANGUAGE UndecidableInstances #-} -- MonadBase module Hedgehog.Internal.Gen (   -- * Transformer-    Gen(..)+    Gen+  , GenT(..)+  , MonadGen(..)    -- * Combinators+  , lift+   -- ** Shrinking   , shrink   , prune@@ -85,6 +91,7 @@    -- ** Conditional   , discard+  , ensure   , filter   , just @@ -120,8 +127,8 @@   -- $internal    -- ** Transfomer-  , runGen-  , mapGen+  , runGenT+  , mapGenT   , generate   , liftTree   , runDiscardEffect@@ -145,25 +152,36 @@   ) where  import           Control.Applicative (Alternative(..))-import           Control.Monad (MonadPlus(..), mfilter, filterM, replicateM, ap, join)+import           Control.Monad (MonadPlus(..), filterM, replicateM, ap, join) import           Control.Monad.Base (MonadBase(..)) import           Control.Monad.Catch (MonadThrow(..), MonadCatch(..)) import           Control.Monad.Error.Class (MonadError(..)) import           Control.Monad.IO.Class (MonadIO(..))-import           Control.Monad.Morph (MFunctor(..), MMonad(..))+import           Control.Monad.Morph (MFunctor(..), MMonad(..), generalize) import           Control.Monad.Primitive (PrimMonad(..)) import           Control.Monad.Reader.Class (MonadReader(..)) import           Control.Monad.State.Class (MonadState(..))-import           Control.Monad.Trans.Class (MonadTrans(..))-import           Control.Monad.Trans.Maybe (MaybeT(..))+import           Control.Monad.Trans.Class (MonadTrans)+import qualified Control.Monad.Trans.Class as Trans+import           Control.Monad.Trans.Except (ExceptT(..), mapExceptT)+import           Control.Monad.Trans.Identity (IdentityT(..), mapIdentityT)+import           Control.Monad.Trans.Maybe (MaybeT(..), mapMaybeT)+import qualified Control.Monad.Trans.RWS.Lazy as Lazy+import qualified Control.Monad.Trans.RWS.Strict as Strict+import           Control.Monad.Trans.Reader (ReaderT(..), mapReaderT) import           Control.Monad.Trans.Resource (MonadResource(..))+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict import           Control.Monad.Writer.Class (MonadWriter(..)) -import           Data.Bifunctor (first)+import           Data.Bifunctor (first, second) import           Data.ByteString (ByteString) import qualified Data.ByteString as ByteString import qualified Data.Char as Char import           Data.Foldable (for_, toList)+import           Data.Functor.Identity (Identity(..)) import           Data.Int (Int8, Int16, Int32, Int64) import           Data.List.NonEmpty (NonEmpty) import qualified Data.List.NonEmpty as NonEmpty@@ -195,53 +213,35 @@  -- | Generator for random values of @a@. ---newtype Gen m a =-  Gen {+type Gen =+  GenT Identity++-- | Monad transformer which can generate random values of @a@.+--+newtype GenT m a =+  GenT {       unGen :: Size -> Seed -> Tree (MaybeT m) a     }  -- | Runs a generator, producing its shrink tree. ---runGen :: Size -> Seed -> Gen m a -> Tree (MaybeT m) a-runGen size seed (Gen m) =+runGenT :: Size -> Seed -> GenT m a -> Tree (MaybeT m) a+runGenT size seed (GenT m) =   m size seed  -- | Map over a generator's shrink tree. ---mapGen :: (Tree (MaybeT m) a -> Tree (MaybeT n) b) -> Gen m a -> Gen n b-mapGen f gen =-  Gen $ \size seed ->-    f (runGen size seed gen)---- | Generate a value with no shrinks from a 'Size' and a 'Seed'.----generate :: Monad m => (Size -> Seed -> a) -> Gen m a-generate f =-  Gen $ \size seed ->-    pure (f size seed)---- | Freeze the size and seed used by a generator, so we can inspect the value---   which it will produce.------   This is used for implementing `list` and `subtermMVec`. It allows us to---   shrink the list itself before trying to shrink the values inside the list.----freeze :: Monad m => Gen m a -> Gen m (a, Gen m a)-freeze gen =-  Gen $ \size seed -> do-    mx <- lift . lift . runMaybeT . runTree $ runGen size seed gen-    case mx of-      Nothing ->-        mzero-      Just (Node x xs) ->-        pure (x, liftTree . Tree.fromNode $ Node x xs)+mapGenT :: (Tree (MaybeT m) a -> Tree (MaybeT n) b) -> GenT m a -> GenT n b+mapGenT f gen =+  GenT $ \size seed ->+    f (runGenT size seed gen)  -- | Lift a predefined shrink tree in to a generator, ignoring the seed and the --   size. ---liftTree :: Tree (MaybeT m) a -> Gen m a+liftTree :: Tree (MaybeT m) a -> GenT m a liftTree x =-  Gen (\_ _ -> x)+  GenT (\_ _ -> x)  -- | Run the discard effects through the tree and reify them as 'Maybe' values --   at the nodes. 'Nothing' means discarded, 'Just' means we have a value.@@ -251,54 +251,321 @@   runMaybeT . distribute  --------------------------------------------------------------------------- Gen instances+-- MonadGen -instance Functor m => Functor (Gen m) where+-- | Class of monads which can generate input data for tests.+--+--   /The functions on this class can, and should, be used without their @Gen@/+--   /suffix by importing "Hedgehog.Gen" qualified./+--+class Monad m => MonadGen m where+  -- | See @Gen.@'Hedgehog.Gen.lift'+  --+  liftGen :: Gen a -> m a++  -- | See @Gen.@'Hedgehog.Gen.shrink'+  --+  shrinkGen :: (a -> [a]) -> m a -> m a++  -- | See @Gen.@'Hedgehog.Gen.prune'+  --+  pruneGen :: m a -> m a++  -- | See @Gen.@'Hedgehog.Gen.scale'+  --+  scaleGen :: (Size -> Size) -> m a -> m a++  -- | See @Gen.@'Hedgehog.Gen.freeze'+  --+  freezeGen :: m a -> m (a, m a)++instance Monad m => MonadGen (GenT m) where+  liftGen gen =+    hoist generalize gen++  shrinkGen =+    mapGenT . Tree.expand++  pruneGen =+    mapGenT Tree.prune++  scaleGen f gen =+    GenT $ \size0 seed ->+      let+        size =+          f size0+      in+        if size < 0 then+          error "Hedgehog.Gen.scale: negative size"+        else+          runGenT size seed gen++  freezeGen gen =+    GenT $ \size seed -> do+      mx <- Trans.lift . Trans.lift . runMaybeT . runTree $ runGenT size seed gen+      case mx of+        Nothing ->+          mzero+        Just (Node x xs) ->+          pure (x, liftTree . Tree.fromNode $ Node x xs)++instance MonadGen m => MonadGen (IdentityT m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    mapIdentityT (shrink f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen =+    mapIdentityT $+      fmap (second Trans.lift) . freeze++shrinkMaybe :: (a -> [a]) -> Maybe a -> [Maybe a]+shrinkMaybe f = \case+  Nothing ->+    pure Nothing+  Just x ->+    fmap Just (f x)++shrinkEither :: (a -> [a]) -> Either x a -> [Either x a]+shrinkEither f = \case+  Left x ->+    pure $ Left x+  Right x ->+    fmap Right (f x)++shrink2 :: (a -> [a]) -> (a, b) -> [(a, b)]+shrink2 f (x, y) =+  fmap (, y) (f x)++shrink3 :: (a -> [a]) -> (a, b, c) -> [(a, b, c)]+shrink3 f (x, y, z) =+  fmap (, y, z) (f x)++instance MonadGen m => MonadGen (MaybeT m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    mapMaybeT $+      shrink (shrinkMaybe f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen =+    mapMaybeT $ \m0 -> do+      (mx, m) <- freeze m0+      pure $ fmap (, MaybeT m) mx++instance MonadGen m => MonadGen (ExceptT x m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    mapExceptT $+      shrink (shrinkEither f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen =+    mapExceptT $ \m0 -> do+      (mx, m) <- freeze m0+      pure $ fmap (, ExceptT m) mx++instance MonadGen m => MonadGen (ReaderT r m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    mapReaderT (shrink f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen =+    mapReaderT $+      fmap (second Trans.lift) . freeze++instance MonadGen m => MonadGen (Lazy.StateT s m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    Lazy.mapStateT $+      shrink (shrink2 f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen m0 =+    Lazy.StateT $ \s0 -> do+      ((x, s), m) <- freeze (Lazy.runStateT m0 s0)+      pure ((x, Lazy.StateT (const m)), s)++instance MonadGen m => MonadGen (Strict.StateT s m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    Strict.mapStateT $+      shrink (shrink2 f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen m0 =+    Strict.StateT $ \s0 -> do+      ((x, s), m) <- freeze (Strict.runStateT m0 s0)+      pure ((x, Strict.StateT (const m)), s)++instance (MonadGen m, Monoid w) => MonadGen (Lazy.WriterT w m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    Lazy.mapWriterT $+      shrink (shrink2 f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen m0 =+    Lazy.WriterT $ do+      ((x, w), m) <- freeze (Lazy.runWriterT m0)+      pure ((x, Lazy.WriterT m), w)++instance (MonadGen m, Monoid w) => MonadGen (Strict.WriterT w m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    Strict.mapWriterT $+      shrink (shrink2 f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen m0 =+    Strict.WriterT $ do+      ((x, w), m) <- freeze (Strict.runWriterT m0)+      pure ((x, Strict.WriterT m), w)++instance (MonadGen m, Monoid w) => MonadGen (Lazy.RWST r w s m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    Lazy.mapRWST $+      shrink (shrink3 f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen m0 =+    Lazy.RWST $ \r s0 -> do+      ((x, s, w), m) <- freeze (Lazy.runRWST m0 r s0)+      pure ((x, Lazy.RWST (\_ _ -> m)), s, w)++instance (MonadGen m, Monoid w) => MonadGen (Strict.RWST r w s m) where+  liftGen =+    Trans.lift . liftGen++  shrinkGen f =+    Strict.mapRWST $+      shrink (shrink3 f)++  pruneGen =+    hoist prune++  scaleGen f =+    hoist (scale f)++  freezeGen m0 =+    Strict.RWST $ \r s0 -> do+      ((x, s, w), m) <- freeze (Strict.runRWST m0 r s0)+      pure ((x, Strict.RWST (\_ _ -> m)), s, w)++------------------------------------------------------------------------+-- GenT instances++instance Functor m => Functor (GenT m) where   fmap f gen =-    Gen $ \seed size ->-      fmap f (runGen seed size gen)+    GenT $ \seed size ->+      fmap f (runGenT seed size gen) -instance Monad m => Applicative (Gen m) where+instance Monad m => Applicative (GenT m) where   pure =     return   (<*>) =     ap -instance Monad m => Monad (Gen m) where+instance Monad m => Monad (GenT m) where   return =     liftTree . pure    (>>=) m k =-    Gen $ \size seed ->+    GenT $ \size seed ->       case Seed.split seed of         (sk, sm) ->-          runGen size sk . k =<<-          runGen size sm m+          runGenT size sk . k =<<+          runGenT size sm m -instance Monad m => Alternative (Gen m) where+instance Monad m => Alternative (GenT m) where   empty =     mzero   (<|>) =     mplus -instance Monad m => MonadPlus (Gen m) where+instance Monad m => MonadPlus (GenT m) where   mzero =     liftTree mzero    mplus x y =-    Gen $ \size seed ->+    GenT $ \size seed ->       case Seed.split seed of         (sx, sy) ->-          runGen size sx x `mplus`-          runGen size sy y+          runGenT size sx x `mplus`+          runGenT size sy y -instance MonadTrans Gen where+instance MonadTrans GenT where   lift =-    liftTree . lift . lift+    liftTree . Trans.lift . Trans.lift -instance MFunctor Gen where+instance MFunctor GenT where   hoist f =-    mapGen (hoist (hoist f))+    mapGenT (hoist (hoist f))  embedMaybe ::      MonadTrans t@@ -308,32 +575,32 @@   -> MaybeT m b   -> t (MaybeT n) b embedMaybe f m =-  lift . MaybeT . pure =<< f (runMaybeT m)+  Trans.lift . MaybeT . pure =<< f (runMaybeT m)  embedTree :: Monad n => (forall a. m a -> Tree (MaybeT n) a) -> Tree (MaybeT m) b -> Tree (MaybeT n) b embedTree f tree =   embed (embedMaybe f) tree -embedGen :: Monad n => (forall a. m a -> Gen n a) -> Gen m b -> Gen n b+embedGen :: Monad n => (forall a. m a -> GenT n a) -> GenT m b -> GenT n b embedGen f gen =-  Gen $ \size seed ->+  GenT $ \size seed ->     case Seed.split seed of       (sf, sg) ->-        (runGen size sf . f) `embedTree`-        (runGen size sg gen)+        (runGenT size sf . f) `embedTree`+        (runGenT size sg gen) -instance MMonad Gen where+instance MMonad GenT where   embed =     embedGen -distributeGen :: Transformer t Gen m => Gen (t m) a -> t (Gen m) a+distributeGen :: Transformer t GenT m => GenT (t m) a -> t (GenT m) a distributeGen x =-  join . lift . Gen $ \size seed ->-    pure . hoist liftTree . distribute . hoist distribute $ runGen size seed x+  join . Trans.lift . GenT $ \size seed ->+    pure . hoist liftTree . distribute . hoist distribute $ runGenT size seed x -instance Distributive Gen where-  type Transformer t Gen m = (-      Monad (t (Gen m))+instance Distributive GenT where+  type Transformer t GenT m = (+      Monad (t (GenT m))     , Transformer t MaybeT m     , Transformer t Tree (MaybeT m)     )@@ -341,119 +608,129 @@   distribute =     distributeGen -instance PrimMonad m => PrimMonad (Gen m) where-  type PrimState (Gen m) =+instance PrimMonad m => PrimMonad (GenT m) where+  type PrimState (GenT m) =     PrimState m   primitive =-    lift . primitive+    Trans.lift . primitive -instance MonadIO m => MonadIO (Gen m) where+instance MonadIO m => MonadIO (GenT m) where   liftIO =-    lift . liftIO+    Trans.lift . liftIO -instance MonadBase b m => MonadBase b (Gen m) where+instance MonadBase b m => MonadBase b (GenT m) where   liftBase =-    lift . liftBase+    Trans.lift . liftBase -instance MonadThrow m => MonadThrow (Gen m) where+instance MonadThrow m => MonadThrow (GenT m) where   throwM =-    lift . throwM+    Trans.lift . throwM -instance MonadCatch m => MonadCatch (Gen m) where+instance MonadCatch m => MonadCatch (GenT m) where   catch m onErr =-    Gen $ \size seed ->+    GenT $ \size seed ->       case Seed.split seed of         (sm, se) ->-          (runGen size sm m) `catch`-          (runGen size se . onErr)+          (runGenT size sm m) `catch`+          (runGenT size se . onErr) -instance MonadReader r m => MonadReader r (Gen m) where+instance MonadReader r m => MonadReader r (GenT m) where   ask =-    lift ask+    Trans.lift ask   local f m =-    mapGen (local f) m+    mapGenT (local f) m -instance MonadState s m => MonadState s (Gen m) where+instance MonadState s m => MonadState s (GenT m) where   get =-    lift get+    Trans.lift get   put =-    lift . put+    Trans.lift . put   state =-    lift . state+    Trans.lift . state -instance MonadWriter w m => MonadWriter w (Gen m) where+instance MonadWriter w m => MonadWriter w (GenT m) where   writer =-    lift . writer+    Trans.lift . writer   tell =-    lift . tell+    Trans.lift . tell   listen =-    mapGen listen+    mapGenT listen   pass =-    mapGen pass+    mapGenT pass -instance MonadError e m => MonadError e (Gen m) where+instance MonadError e m => MonadError e (GenT m) where   throwError =-    lift . throwError+    Trans.lift . throwError   catchError m onErr =-    Gen $ \size seed ->+    GenT $ \size seed ->       case Seed.split seed of         (sm, se) ->-          (runGen size sm m) `catchError`-          (runGen size se . onErr)+          (runGenT size sm m) `catchError`+          (runGenT size se . onErr) -instance MonadResource m => MonadResource (Gen m) where+instance MonadResource m => MonadResource (GenT m) where   liftResourceT =-    lift . liftResourceT+    Trans.lift . liftResourceT  --------------------------------------------------------------------------- Shrinking+-- Combinators +-- | Lift a vanilla 'Gen' in to a 'MonadGen'.+--+lift :: MonadGen m => Gen a -> m a+lift =+  liftGen++-- | Generate a value with no shrinks from a 'Size' and a 'Seed'.+--+generate :: MonadGen m => (Size -> Seed -> a) -> m a+generate f =+  liftGen . GenT $ \size seed ->+    pure (f size seed)++------------------------------------------------------------------------+-- Combinators - Shrinking+ -- | Apply a shrinking function to a generator. -- --   This will give the generator additional shrinking options, while keeping --   the existing shrinks intact. ---shrink :: Monad m => (a -> [a]) -> Gen m a -> Gen m a+shrink :: MonadGen m => (a -> [a]) -> m a -> m a shrink =-  mapGen . Tree.expand+  shrinkGen  -- | Throw away a generator's shrink tree. ---prune :: Monad m => Gen m a -> Gen m a+prune :: MonadGen m => m a -> m a prune =-  mapGen Tree.prune+  pruneGen  ------------------------------------------------------------------------ -- Combinators - Size  -- | Construct a generator that depends on the size parameter. ---sized :: (Size -> Gen m a) -> Gen m a-sized f =-  Gen $ \size seed ->-    runGen size seed (f size)+sized :: MonadGen m => (Size -> m a) -> m a+sized f = do+  f =<< generate (\size _ -> size)  -- | Override the size parameter. Returns a generator which uses the given size --   instead of the runtime-size parameter. ---resize :: Size -> Gen m a -> Gen m a+resize :: MonadGen m => Size -> m a -> m a resize size gen =-  if size < 0 then-    error "Hedgehog.Random.resize: negative size"-  else-    Gen $ \_ seed ->-      runGen size seed gen+  scale (const size) gen  -- | Adjust the size parameter by transforming it with the given function. ---scale :: (Size -> Size) -> Gen m a -> Gen m a-scale f gen =-  sized $ \n ->-    resize (f n) gen+scale :: MonadGen m => (Size -> Size) -> m a -> m a+scale =+  scaleGen  -- | Make a generator smaller by scaling its size parameter. ---small :: Gen m a -> Gen m a+small :: MonadGen m => m a -> m a small =   scale golden @@ -502,7 +779,7 @@ --   > 2058 --   > 2060 ---integral :: (Monad m, Integral a) => Range a -> Gen m a+integral :: (MonadGen m, Integral a) => Range a -> m a integral range =   shrink (Shrink.towards $ Range.origin range) (integral_ range) @@ -510,7 +787,7 @@ -- --   /This generator does not shrink./ ---integral_ :: (Monad m, Integral a) => Range a -> Gen m a+integral_ :: (MonadGen m, Integral a) => Range a -> m a integral_ range =   generate $ \size seed ->     let@@ -524,7 +801,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---int :: Monad m => Range Int -> Gen m Int+int :: MonadGen m => Range Int -> m Int int =   integral @@ -532,7 +809,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---int8 :: Monad m => Range Int8 -> Gen m Int8+int8 :: MonadGen m => Range Int8 -> m Int8 int8 =   integral @@ -540,7 +817,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---int16 :: Monad m => Range Int16 -> Gen m Int16+int16 :: MonadGen m => Range Int16 -> m Int16 int16 =   integral @@ -548,7 +825,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---int32 :: Monad m => Range Int32 -> Gen m Int32+int32 :: MonadGen m => Range Int32 -> m Int32 int32 =   integral @@ -556,7 +833,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---int64 :: Monad m => Range Int64 -> Gen m Int64+int64 :: MonadGen m => Range Int64 -> m Int64 int64 =   integral @@ -564,7 +841,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---word :: Monad m => Range Word -> Gen m Word+word :: MonadGen m => Range Word -> m Word word =   integral @@ -572,7 +849,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---word8 :: Monad m => Range Word8 -> Gen m Word8+word8 :: MonadGen m => Range Word8 -> m Word8 word8 =   integral @@ -580,7 +857,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---word16 :: Monad m => Range Word16 -> Gen m Word16+word16 :: MonadGen m => Range Word16 -> m Word16 word16 =   integral @@ -588,7 +865,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---word32 :: Monad m => Range Word32 -> Gen m Word32+word32 :: MonadGen m => Range Word32 -> m Word32 word32 =   integral @@ -596,7 +873,7 @@ -- --   /This is a specialization of 'integral', offered for convenience./ ---word64 :: Monad m => Range Word64 -> Gen m Word64+word64 :: MonadGen m => Range Word64 -> m Word64 word64 =   integral @@ -607,7 +884,7 @@ -- --   This generator works the same as 'integral', but for floating point numbers. ---realFloat :: (Monad m, RealFloat a) => Range a -> Gen m a+realFloat :: (MonadGen m, RealFloat a) => Range a -> m a realFloat range =   shrink (Shrink.towardsFloat $ Range.origin range) (realFrac_ range) @@ -615,7 +892,7 @@ -- --   /This generator does not shrink./ ---realFrac_ :: (Monad m, RealFrac a) => Range a -> Gen m a+realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a realFrac_ range =   generate $ \size seed ->     let@@ -629,7 +906,7 @@ -- --   /This is a specialization of 'realFloat', offered for convenience./ ---float :: Monad m => Range Float -> Gen m Float+float :: MonadGen m => Range Float -> m Float float =  realFloat @@ -637,7 +914,7 @@ -- --   /This is a specialization of 'realFloat', offered for convenience./ ---double :: Monad m => Range Double -> Gen m Double+double :: MonadGen m => Range Double -> m Double double =  realFloat @@ -654,7 +931,7 @@ -- enum \'a' \'z' :: 'Gen' 'Char' -- @ ---enum :: (Monad m, Enum a) => a -> a -> Gen m a+enum :: (MonadGen m, Enum a) => a -> a -> m a enum lo hi =   fmap toEnum . integral $     Range.constant (fromEnum lo) (fromEnum hi)@@ -669,7 +946,7 @@ -- enumBounded :: 'Gen' 'Bool' -- @ ---enumBounded :: (Monad m, Enum a, Bounded a) => Gen m a+enumBounded :: (MonadGen m, Enum a, Bounded a) => m a enumBounded =   enum minBound maxBound @@ -679,7 +956,7 @@ -- --   /This is a specialization of 'enumBounded', offered for convenience./ ---bool :: Monad m => Gen m Bool+bool :: MonadGen m => m Bool bool =   enumBounded @@ -687,7 +964,7 @@ -- --   /This generator does not shrink./ ---bool_ :: Monad m => Gen m Bool+bool_ :: MonadGen m => m Bool bool_ =   generate $ \_ seed ->     (/= 0) . fst $ Seed.nextInteger 0 1 seed@@ -697,78 +974,78 @@  -- | Generates an ASCII binit: @'0'..'1'@ ---binit :: Monad m => Gen m Char+binit :: MonadGen m => m Char binit =   enum '0' '1'  -- | Generates an ASCII octit: @'0'..'7'@ ---octit :: Monad m => Gen m Char+octit :: MonadGen m => m Char octit =   enum '0' '7'  -- | Generates an ASCII digit: @'0'..'9'@ ---digit :: Monad m => Gen m Char+digit :: MonadGen m => m Char digit =   enum '0' '9'  -- | Generates an ASCII hexit: @'0'..'9', \'a\'..\'f\', \'A\'..\'F\'@ ---hexit :: Monad m => Gen m Char+hexit :: MonadGen m => m Char hexit =   -- FIXME optimize lookup, use a SmallArray or something.   element "0123456789aAbBcCdDeEfF"  -- | Generates an ASCII lowercase letter: @\'a\'..\'z\'@ ---lower :: Monad m => Gen m Char+lower :: MonadGen m => m Char lower =   enum 'a' 'z'  -- | Generates an ASCII uppercase letter: @\'A\'..\'Z\'@ ---upper :: Monad m => Gen m Char+upper :: MonadGen m => m Char upper =   enum 'A' 'Z'  -- | Generates an ASCII letter: @\'a\'..\'z\', \'A\'..\'Z\'@ ---alpha :: Monad m => Gen m Char+alpha :: MonadGen m => m Char alpha =   -- FIXME optimize lookup, use a SmallArray or something.   element "abcdefghiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"  -- | Generates an ASCII letter or digit: @\'a\'..\'z\', \'A\'..\'Z\', \'0\'..\'9\'@ ---alphaNum :: Monad m => Gen m Char+alphaNum :: MonadGen m => m Char alphaNum =   -- FIXME optimize lookup, use a SmallArray or something.   element "abcdefghiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"  -- | Generates an ASCII character: @'\0'..'\127'@ ---ascii :: Monad m => Gen m Char+ascii :: MonadGen m => m Char ascii =   enum '\0' '\127'  -- | Generates a Latin-1 character: @'\0'..'\255'@ ---latin1 :: Monad m => Gen m Char+latin1 :: MonadGen m => m Char latin1 =   enum '\0' '\255'  -- | Generates a Unicode character, excluding invalid standalone surrogates: --   @'\0'..'\1114111' (excluding '\55296'..'\57343')@ ---unicode :: Monad m => Gen m Char+unicode :: MonadGen m => m Char unicode =   filter (not . isSurrogate) unicodeAll  -- | Generates a Unicode character, including invalid standalone surrogates: --   @'\0'..'\1114111'@ ---unicodeAll :: Monad m => Gen m Char+unicodeAll :: MonadGen m => m Char unicodeAll =   enumBounded @@ -785,26 +1062,26 @@ -- --   /This is a specialization of 'list', offered for convenience./ ---string :: Monad m => Range Int -> Gen m Char -> Gen m String+string :: MonadGen m => Range Int -> m Char -> m String string =   list  -- | Generates a string using 'Range' to determine the length. ---text :: Monad m => Range Int -> Gen m Char -> Gen m Text+text :: MonadGen m => Range Int -> m Char -> m Text text range =   fmap Text.pack . string range  -- | Generates a UTF-8 encoded string, using 'Range' to determine the length. ---utf8 :: Monad m => Range Int -> Gen m Char -> Gen m ByteString+utf8 :: MonadGen m => Range Int -> m Char -> m ByteString utf8 range =   fmap Text.encodeUtf8 . text range  -- | Generates a random 'ByteString', using 'Range' to determine the --   length. ---bytes :: Monad m => Range Int -> Gen m ByteString+bytes :: MonadGen m => Range Int -> m ByteString bytes range =   fmap ByteString.pack $   choice [@@ -823,7 +1100,7 @@ -- | Trivial generator that always produces the same element. -- --   /This is another name for 'pure' \/ 'return'./-constant :: Monad m => a -> Gen m a+constant :: MonadGen m => a -> m a constant =   pure @@ -833,7 +1110,7 @@ -- --   /The input list must be non-empty./ ---element :: Monad m => [a] -> Gen m a+element :: MonadGen m => [a] -> m a element = \case   [] ->     error "Hedgehog.Gen.element: used with empty list"@@ -847,7 +1124,7 @@ -- --   /The input list must be non-empty./ ---choice :: Monad m => [Gen m a] -> Gen m a+choice :: MonadGen m => [m a] -> m a choice = \case   [] ->     error "Hedgehog.Gen.choice: used with empty list"@@ -862,7 +1139,7 @@ -- --   /The input list must be non-empty./ ---frequency :: Monad m => [(Int, Gen m a)] -> Gen m a+frequency :: MonadGen m => [(Int, m a)] -> m a frequency = \case   [] ->     error "Hedgehog.Gen.frequency: used with empty list"@@ -901,10 +1178,10 @@ --   | App Expr Expr -- -- -- Assuming we have a name generator--- genName :: 'Monad' m => 'Gen' m String+-- genName :: 'MonadGen' m => m String -- -- -- We can write a generator for expressions--- genExpr :: 'Monad' m => 'Gen' m Expr+-- genExpr :: 'MonadGen' m => m Expr -- genExpr = --   Gen.'recursive' Gen.'choice' [ --       -- non-recursive generators@@ -920,7 +1197,7 @@ --   would fail to terminate. This is because for every call to @genExpr@, --   there is a 2 in 3 chance that we will recurse again. ---recursive :: ([Gen m a] -> Gen m a) -> [Gen m a] -> [Gen m a] -> Gen m a+recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a recursive f nonrec rec =   sized $ \n ->     if n <= 1 then@@ -933,12 +1210,21 @@  -- | Discards the whole generator. -----   /This is another name for 'empty' \/ 'mzero'./----discard :: Monad m => Gen m a+discard :: MonadGen m => m a discard =-  mzero+  liftGen mzero +-- | Discards the generator if the generated value does not satisfy the+--   predicate.+--+ensure :: MonadGen m => (a -> Bool) -> m a -> m a+ensure p gen = do+  x <- gen+  if p x then+    pure x+  else+    discard+ -- | Generates a value that satisfies a predicate. -- --   This is essentially:@@ -950,14 +1236,18 @@ --   It differs from the above in that we keep some state to avoid looping --   forever. If we trigger these limits then the whole generator is discarded. ---filter :: Monad m => (a -> Bool) -> Gen m a -> Gen m a+filter :: MonadGen m => (a -> Bool) -> m a -> m a filter p gen =   let     try k =       if k > 100 then-        empty-      else-        mfilter p (scale (2 * k +) gen) <|> try (k + 1)+        discard+      else do+        x <- scale (2 * k +) gen+        if p x then+          pure x+        else+          try (k + 1)   in     try 0 @@ -965,7 +1255,7 @@ -- --   This is implemented using 'filter' and has the same caveats. ---just :: Monad m => Gen m (Maybe a) -> Gen m a+just :: MonadGen m => m (Maybe a) -> m a just g = do   mx <- filter Maybe.isJust g   case mx of@@ -979,7 +1269,7 @@  -- | Generates a 'Nothing' some of the time. ---maybe :: Monad m => Gen m a -> Gen m (Maybe a)+maybe :: MonadGen m => m a -> m (Maybe a) maybe gen =   sized $ \n ->     frequency [@@ -989,24 +1279,24 @@  -- | Generates a list using a 'Range' to determine the length. ---list :: Monad m => Range Int -> Gen m a -> Gen m [a]+list :: MonadGen m => Range Int -> m a -> m [a] list range gen =   sized $ \size ->     (traverse snd =<<) .-    mfilter (atLeast $ Range.lowerBound size range) .+    ensure (atLeast $ Range.lowerBound size range) .     shrink Shrink.list $ do       k <- integral_ range       replicateM k (freeze gen)  -- | Generates a seq using a 'Range' to determine the length. ---seq :: Monad m => Range Int -> Gen m a -> Gen m (Seq a)+seq :: MonadGen m => Range Int -> m a -> m (Seq a) seq range gen =   Seq.fromList <$> list range gen  -- | Generates a non-empty list using a 'Range' to determine the length. ---nonEmpty :: Monad m => Range Int -> Gen m a -> Gen m (NonEmpty a)+nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a) nonEmpty range gen = do   xs <- list (fmap (max 1) range) gen   case xs of@@ -1021,7 +1311,7 @@ --   /cannot produce a large enough number of unique items to satify/ --   /the required set size./ ---set :: (Monad m, Ord a) => Range Int -> Gen m a -> Gen m (Set a)+set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a) set range gen =   fmap Map.keysSet . map range $ fmap (, ()) gen @@ -1031,10 +1321,10 @@ --   /generator do not account for a large enough number of unique/ --   /items to satify the required map size./ ---map :: (Monad m, Ord k) => Range Int -> Gen m (k, v) -> Gen m (Map k v)+map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v) map range gen =   sized $ \size ->-    mfilter ((>= Range.lowerBound size range) . Map.size) .+    ensure ((>= Range.lowerBound size range) . Map.size) .     fmap Map.fromList .     (sequence =<<) .     shrink Shrink.list $ do@@ -1043,12 +1333,12 @@  -- | Generate exactly 'n' unique generators. ---uniqueByKey :: (Monad m, Ord k) => Int -> Gen m (k, v) -> Gen m [Gen m (k, v)]+uniqueByKey :: (MonadGen m, Ord k) => Int -> m (k, v) -> m [m (k, v)] uniqueByKey n gen =   let     try k xs0 =       if k > 100 then-        mzero+        discard       else         replicateM n (freeze gen) >>= \kvs ->         case uniqueInsert n xs0 (fmap (first fst) kvs) of@@ -1101,6 +1391,16 @@ deriving instance Foldable (Vec n) deriving instance Traversable (Vec n) +-- | Freeze the size and seed used by a generator, so we can inspect the value+--   which it will produce.+--+--   This is used for implementing `list` and `subtermMVec`. It allows us to+--   shrink the list itself before trying to shrink the values inside the list.+--+freeze :: MonadGen m => m a -> m (a, m a)+freeze =+  freezeGen+ shrinkSubterms :: Subterms n a -> [Subterms n a] shrinkSubterms = \case   One _ ->@@ -1108,7 +1408,7 @@   All xs ->     fmap One $ toList xs -genSubterms :: Monad m => Vec n (Gen m a) -> Gen m (Subterms n a)+genSubterms :: MonadGen m => Vec n (m a) -> m (Subterms n a) genSubterms =   (sequence =<<) .   shrink shrinkSubterms .@@ -1126,7 +1426,7 @@ -- --   /Shrinks to one of the sub-terms if possible./ ---subtermMVec :: Monad m => Vec n (Gen m a) -> (Vec n a -> Gen m a) -> Gen m a+subtermMVec :: MonadGen m => Vec n (m a) -> (Vec n a -> m a) -> m a subtermMVec gs f =   fromSubterms f =<< genSubterms gs @@ -1134,7 +1434,7 @@ -- --   /Shrinks to the sub-term if possible./ ---subtermM :: Monad m => Gen m a -> (a -> Gen m a) -> Gen m a+subtermM :: MonadGen m => m a -> (a -> m a) -> m a subtermM gx f =   subtermMVec (gx :. Nil) $ \(x :. Nil) ->     f x@@ -1143,7 +1443,7 @@ -- --   /Shrinks to the sub-term if possible./ ---subterm :: Monad m => Gen m a -> (a -> a) -> Gen m a+subterm :: MonadGen m => m a -> (a -> a) -> m a subterm gx f =   subtermM gx $ \x ->     pure (f x)@@ -1152,7 +1452,7 @@ -- --   /Shrinks to one of the sub-terms if possible./ ---subtermM2 :: Monad m => Gen m a -> Gen m a -> (a -> a -> Gen m a) -> Gen m a+subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a subtermM2 gx gy f =   subtermMVec (gx :. gy :. Nil) $ \(x :. y :. Nil) ->     f x y@@ -1161,7 +1461,7 @@ -- --   /Shrinks to one of the sub-terms if possible./ ---subterm2 :: Monad m => Gen m a -> Gen m a -> (a -> a -> a) -> Gen m a+subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a subterm2 gx gy f =   subtermM2 gx gy $ \x y ->     pure (f x y)@@ -1170,7 +1470,7 @@ -- --   /Shrinks to one of the sub-terms if possible./ ---subtermM3 :: Monad m => Gen m a -> Gen m a -> Gen m a -> (a -> a -> a -> Gen m a) -> Gen m a+subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a subtermM3 gx gy gz f =   subtermMVec (gx :. gy :. gz :. Nil) $ \(x :. y :. z :. Nil) ->     f x y z@@ -1179,7 +1479,7 @@ -- --   /Shrinks to one of the sub-terms if possible./ ---subterm3 :: Monad m => Gen m a -> Gen m a -> Gen m a -> (a -> a -> a -> a) -> Gen m a+subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a subterm3 gx gy gz f =   subtermM3 gx gy gz $ \x y z ->     pure (f x y z)@@ -1189,7 +1489,7 @@  -- | Generates a random subsequence of a list. ---subsequence :: Monad m => [a] -> Gen m [a]+subsequence :: MonadGen m => [a] -> m [a] subsequence xs =   shrink Shrink.list $ filterM (const bool_) xs @@ -1198,7 +1498,7 @@ --   This shrinks towards the order of the list being identical to the input --   list. ---shuffle :: Monad m => [a] -> Gen m [a]+shuffle :: MonadGen m => [a] -> m [a] shuffle = \case   [] ->     pure []@@ -1208,44 +1508,61 @@       (xs, y : ys) ->         (y :) <$> shuffle (xs ++ ys)       (_, []) ->-        error "Hedgehog.shuffle: internal error, split generated empty list"+        error "Hedgehog.Gen.shuffle: internal error, split generated empty list"  ------------------------------------------------------------------------ -- Sampling --- | Generate a random sample of data from the a generator.+-- | Generate a sample from a generator. ---sample :: MonadIO m => Gen m a -> m [a]+sample :: MonadIO m => Gen a -> m a sample gen =-  fmap (fmap nodeValue . Maybe.catMaybes) .-  replicateM 10 $ do-    seed <- liftIO Seed.random-    runMaybeT . runTree $ runGen 30 seed gen+  liftIO $+    let+      loop n =+        if n <= 0 then+          error "Hedgehog.Gen.sample: too many discards, could not generate a sample"+        else do+          seed <- Seed.random+          case runIdentity . runMaybeT . runTree $ runGenT 30 seed gen of+            Nothing ->+              loop (n - 1)+            Just x ->+              pure $ nodeValue x+    in+      loop (100 :: Int)  -- | Print the value produced by a generator, and the first level of shrinks, --   for the given size and seed. -- --   Use 'print' to generate a value from a random seed. ---printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen m a -> m ()-printWith size seed gen = do-  Node x ss <- runTree $ renderNodes size seed gen-  liftIO $ putStrLn "=== Outcome ==="-  liftIO $ putStrLn x-  liftIO $ putStrLn "=== Shrinks ==="-  for_ ss $ \s -> do-    Node y _ <- runTree s-    liftIO $ putStrLn y+printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m ()+printWith size seed gen =+  liftIO $ do+    let+      Node x ss =+        runIdentity . runTree $ renderNodes size seed gen +    putStrLn "=== Outcome ==="+    putStrLn x+    putStrLn "=== Shrinks ==="++    for_ ss $ \s ->+      let+        Node y _ =+          runIdentity $ runTree s+      in+        putStrLn y+ -- | Print the shrink tree produced by a generator, for the given size and --   seed. -- --   Use 'printTree' to generate a value from a random seed. ---printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen m a -> m ()+printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () printTreeWith size seed gen = do-  s <- Tree.render $ renderNodes size seed gen-  liftIO $ putStr s+  liftIO . putStr . runIdentity . Tree.render $ renderNodes size seed gen  -- | Run a generator with a random seed and print the outcome, and the first --   level of shrinks.@@ -1261,7 +1578,7 @@ --   > 'b' --   > 'c' ---print :: (MonadIO m, Show a) => Gen m a -> m ()+print :: (MonadIO m, Show a) => Gen a -> m () print gen = do   seed <- liftIO Seed.random   printWith 30 seed gen@@ -1283,16 +1600,16 @@ -- --   /This may not terminate when the tree is very large./ ---printTree :: (MonadIO m, Show a) => Gen m a -> m ()+printTree :: (MonadIO m, Show a) => Gen a -> m () printTree gen = do   seed <- liftIO Seed.random   printTreeWith 30 seed gen  -- | Render a generator as a tree of strings. ---renderNodes :: (Monad m, Show a) => Size -> Seed -> Gen m a -> Tree m String+renderNodes :: (Monad m, Show a) => Size -> Seed -> Gen a -> Tree m String renderNodes size seed =-  fmap (Maybe.maybe "<discard>" show) . runDiscardEffect . runGen size seed+  fmap (Maybe.maybe "<discard>" show) . runDiscardEffect . runGenT size seed . lift  ------------------------------------------------------------------------ -- Internal
src/Hedgehog/Internal/Opaque.hs view
@@ -11,8 +11,10 @@ --   For example: -- -- @---   data Ref v =---     Ref (v (Opaque (IORef Int)))+--   data State v =+--     State {+--         stateRefs :: [Var (Opaque (IORef Int)) v]+--       } deriving (Eq, Show) -- @ -- newtype Opaque a =
src/Hedgehog/Internal/Property.hs view
@@ -8,66 +8,79 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-} -- MonadBase+{-# LANGUAGE UndecidableInstances #-} -- Distributive module Hedgehog.Internal.Property (   -- * Property     Property(..)+  , PropertyT(..)   , PropertyName(..)   , PropertyConfig(..)   , TestLimit(..)   , DiscardLimit(..)   , ShrinkLimit(..)-  , property+  , ShrinkRetries(..)   , withTests   , withDiscards   , withShrinks+  , withRetries+  , property+  , test+  , forAll+  , forAllT+  , forAllWith+  , forAllWithT+  , discard    -- * Group   , Group(..)   , GroupName(..) -  -- * Test-  , Test(..)+  -- * TestT+  , MonadTest(..)+  , Test+  , TestT(..)   , Log(..)   , Failure(..)   , Diff(..)-  , forAll-  , forAllWith   , annotate   , annotateShow   , footnote   , footnoteShow-  , discard   , failure   , success   , assert   , (===) -  , liftCatch-  , liftCatchIO-  , liftEither-  , liftExceptT--  , withCatch-  , withExceptT-  , withResourceT+  , eval+  , evalM+  , evalIO+  , evalEither+  , evalExceptT    -- * Internal   -- $internal   , defaultConfig   , mapConfig+  , failDiff+  , failException   , failWith   , writeLog++  , mkTest+  , mkTestT   , runTest+  , runTestT   ) where  import           Control.Applicative (Alternative(..)) import           Control.Monad (MonadPlus(..)) import           Control.Monad.Base (MonadBase(..)) import           Control.Monad.Catch (MonadThrow(..), MonadCatch(..))+import           Control.Monad.Catch (SomeException(..), displayException) import           Control.Monad.Error.Class (MonadError(..)) import           Control.Monad.IO.Class (MonadIO(..)) import           Control.Monad.Morph (MFunctor(..))@@ -75,18 +88,32 @@ import           Control.Monad.Reader.Class (MonadReader(..)) import           Control.Monad.State.Class (MonadState(..)) import           Control.Monad.Trans.Class (MonadTrans(..))+import           Control.Monad.Trans.Cont (ContT)+import           Control.Monad.Trans.Control (ComposeSt, defaultLiftBaseWith, defaultRestoreM)+import           Control.Monad.Trans.Control (MonadBaseControl(..), MonadTransControl(..)) import           Control.Monad.Trans.Except (ExceptT(..), runExceptT)-import           Control.Monad.Trans.Resource (MonadResource(..), MonadResourceBase)-import           Control.Monad.Trans.Resource (ResourceT, runResourceT)-import           Control.Monad.Trans.Writer.Lazy (WriterT(..))-import           Control.Monad.Writer.Class (MonadWriter(..))+import           Control.Monad.Trans.Identity (IdentityT)+import           Control.Monad.Trans.Maybe (MaybeT)+import qualified Control.Monad.Trans.RWS.Lazy as Lazy+import qualified Control.Monad.Trans.RWS.Strict as Strict+import           Control.Monad.Trans.Reader (ReaderT)+import           Control.Monad.Trans.Resource (MonadResource(..))+import           Control.Monad.Trans.Resource (ResourceT)+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict +import qualified Data.Char as Char+import           Data.Functor.Identity (Identity(..))+import qualified Data.List as List import           Data.Semigroup (Semigroup) import           Data.String (IsString)+import           Data.Typeable (typeOf)  import           Hedgehog.Internal.Distributive import           Hedgehog.Internal.Exception-import           Hedgehog.Internal.Gen (Gen)+import           Hedgehog.Internal.Gen (Gen, GenT) import qualified Hedgehog.Internal.Gen as Gen import           Hedgehog.Internal.Show import           Hedgehog.Internal.Source@@ -95,24 +122,63 @@  ------------------------------------------------------------------------ --- | A property test to check, along with some configurable limits like how---   many times to run the test.+-- | A property test, along with some configurable limits like how many times+--   to run the test. -- data Property =   Property {       propertyConfig :: !PropertyConfig-    , propertyTest :: Test IO ()+    , propertyTest :: PropertyT IO ()     } --- | A property test.+-- | The property monad transformer allows both the generation of test inputs+--   and the assertion of expectations. ---newtype Test m a =-  Test {-      unTest :: ExceptT Failure (WriterT [Log] (Gen m)) a-    } deriving (Functor, Applicative)+newtype PropertyT m a =+  PropertyT {+      unPropertyT :: TestT (GenT m) a+    } deriving (+      Functor+    , Applicative+    , Monad+    , MonadIO+    , MonadBase b+    , MonadThrow+    , MonadCatch+    , MonadReader r+    , MonadState s+    , MonadError e+    ) +-- | A test monad allows the assertion of expectations.+--+type Test =+  TestT Identity++-- | A test monad transformer allows the assertion of expectations.+--+newtype TestT m a =+  TestT {+      unTest :: ExceptT Failure (Lazy.WriterT [Log] m) a+    } deriving (+      Functor+    , Applicative+    , MonadIO+    , MonadBase b+    , MonadThrow+    , MonadCatch+    , MonadReader r+    , MonadState s+    )+ -- | The name of a property. --+--   Can be constructed using `OverloadedStrings`:+--+-- @+--   "apples" :: PropertyName+-- @+-- newtype PropertyName =   PropertyName {       unPropertyName :: String@@ -125,25 +191,64 @@       propertyTestLimit :: !TestLimit     , propertyDiscardLimit :: !DiscardLimit     , propertyShrinkLimit :: !ShrinkLimit+    , propertyShrinkRetries :: !ShrinkRetries     } deriving (Eq, Ord, Show)  -- | The number of successful tests that need to be run before a property test --   is considered successful. --+--   Can be constructed using numeric literals:+--+-- @+--   200 :: TestLimit+-- @+-- newtype TestLimit =   TestLimit Int   deriving (Eq, Ord, Show, Num, Enum, Real, Integral) +-- | The number of discards to allow before giving up.+--+--   Can be constructed using numeric literals:+--+-- @+--   10000 :: DiscardLimit+-- @+--+--+newtype DiscardLimit =+  DiscardLimit Int+  deriving (Eq, Ord, Show, Num, Enum, Real, Integral)+ -- | The number of shrinks to try before giving up on shrinking. --+--   Can be constructed using numeric literals:+--+-- @+--   1000 :: ShrinkLimit+-- @+-- newtype ShrinkLimit =   ShrinkLimit Int   deriving (Eq, Ord, Show, Num, Enum, Real, Integral) --- | The number of discards to allow before giving up.+-- | The number of times to re-run a test during shrinking. This is useful if+--   you are testing something which fails non-deterministically and you want to+--   increase the change of getting a good shrink. ---newtype DiscardLimit =-  DiscardLimit Int+--   If you are doing parallel state machine testing, you should probably set+--   shrink retries to something like @10@. This will mean that during+--   shrinking, a parallel test case requires 10 successful runs before it is+--   passes and we try a different shrink.+--+--   Can be constructed using numeric literals:+--+-- @+--   0 :: ShrinkRetries+-- @+--+newtype ShrinkRetries =+  ShrinkRetries Int   deriving (Eq, Ord, Show, Num, Enum, Real, Integral)  -- | A named collection of property tests.@@ -156,6 +261,12 @@  -- | The name of a group of properties. --+--   Can be constructed using `OverloadedStrings`:+--+-- @+--   "fruit" :: GroupName+-- @+-- newtype GroupName =   GroupName {       unGroupName :: String@@ -192,246 +303,238 @@     , diffValue :: ValueDiff     } deriving (Eq, Show) -instance Monad m => Monad (Test m) where+------------------------------------------------------------------------+-- TestT++instance Monad m => Monad (TestT m) where   return =-    Test . return+    TestT . return    (>>=) m k =-    Test $+    TestT $       unTest m >>=       unTest . k    fail err =-    Test . ExceptT . pure . Left $ Failure Nothing err Nothing--instance Monad m => MonadPlus (Test m) where-  mzero =-    discard--  mplus x y =-    Test . ExceptT . WriterT $-      mplus (runTest x) (runTest y)--instance Monad m => Alternative (Test m) where-  empty =-    mzero-  (<|>) =-    mplus+    TestT . ExceptT . pure . Left $ Failure Nothing err Nothing -instance MonadTrans Test where+instance MonadTrans TestT where   lift =-    Test . lift . lift . lift+    TestT . lift . lift -instance MFunctor Test where+instance MFunctor TestT where   hoist f =-    Test . hoist (hoist (hoist f)) . unTest--distributeTest :: Transformer t Test m => Test (t m) a -> t (Test m) a-distributeTest =-  hoist Test .-  distribute .-  hoist distribute .-  hoist (hoist distribute) .-  unTest+    TestT . hoist (hoist f) . unTest -instance Distributive Test where-  type Transformer t Test m = (-      Transformer t Gen m-    , Transformer t (WriterT [Log]) (Gen m)-    , Transformer t (ExceptT Failure) (WriterT [Log] (Gen m))+instance Distributive TestT where+  type Transformer t TestT m = (+      Transformer t (Lazy.WriterT [Log]) m+    , Transformer t (ExceptT Failure) (Lazy.WriterT [Log] m)     )    distribute =-    distributeTest+    hoist TestT .+    distribute .+    hoist distribute .+    unTest -instance PrimMonad m => PrimMonad (Test m) where-  type PrimState (Test m) =+instance PrimMonad m => PrimMonad (TestT m) where+  type PrimState (TestT m) =     PrimState m   primitive =     lift . primitive -instance MonadIO m => MonadIO (Test m) where-  liftIO =-    lift . liftIO--instance MonadBase b m => MonadBase b (Test m) where-  liftBase =-    lift . liftBase--instance MonadThrow m => MonadThrow (Test m) where-  throwM =-    lift . throwM--instance MonadCatch m => MonadCatch (Test m) where-  catch m onErr =-    Test $-      (unTest m) `catch`-      (unTest . onErr)--instance MonadReader r m => MonadReader r (Test m) where-  ask =-    lift ask-  local f m =-    Test $-      local f (unTest m)--instance MonadState s m => MonadState s (Test m) where-  get =-    lift get-  put =-    lift . put-  state =-    lift . state---- FIXME instance MonadWriter Test+-- FIXME instance MonadWriter w m => MonadWriter w (TestT m) -instance MonadError e m => MonadError e (Test m) where+instance MonadError e m => MonadError e (TestT m) where   throwError =     lift . throwError   catchError m onErr =-    Test . ExceptT $+    TestT . ExceptT $       (runExceptT $ unTest m) `catchError`       (runExceptT . unTest . onErr) -instance MonadResource m => MonadResource (Test m) where+instance MonadResource m => MonadResource (TestT m) where   liftResourceT =     lift . liftResourceT ---------------------------------------------------------------------------- Property+instance MonadTransControl TestT where+  type StT TestT a =+    (Either Failure a, [Log]) --- | The default configuration for a property test.----defaultConfig :: PropertyConfig-defaultConfig =-  PropertyConfig {-      propertyTestLimit =-        100-    , propertyDiscardLimit =-        100-    , propertyShrinkLimit =-        1000-    }+  liftWith f =+    mkTestT . fmap (, []) . fmap Right $ f $ runTestT --- | Map a config modification function over a property.----mapConfig :: (PropertyConfig -> PropertyConfig) -> Property -> Property-mapConfig f (Property cfg t) =-  Property (f cfg) t+  restoreT =+    mkTestT --- | Set the number times a property should be executed before it is considered---   successful.----withTests :: TestLimit -> Property -> Property-withTests n =-  mapConfig $ \config -> config { propertyTestLimit = n }+instance MonadBaseControl b m => MonadBaseControl b (TestT m) where+  type StM (TestT m) a =+    ComposeSt TestT m a --- | Set the number times a property is allowed to discard before the test---   runner gives up.----withDiscards :: DiscardLimit -> Property -> Property-withDiscards n =-  mapConfig $ \config -> config { propertyDiscardLimit = n }+  liftBaseWith =+    defaultLiftBaseWith --- | Set the number times a property is allowed to shrink before the test---   runner gives up and prints the counterexample.----withShrinks :: ShrinkLimit -> Property -> Property-withShrinks n =-  mapConfig $ \config -> config { propertyShrinkLimit = n }+  restoreM =+    defaultRestoreM --- | Creates a property to check.----property :: Test IO () -> Property-property =-  Property defaultConfig+class Monad m => MonadTest m where+  liftTest :: Test a -> m a ---------------------------------------------------------------------------- Test+instance Monad m => MonadTest (TestT m) where+  liftTest =+    hoist (pure . runIdentity) -runTest :: Test m a -> Gen m (Either Failure a, [Log])-runTest =-  runWriterT . runExceptT . unTest+instance MonadTest m => MonadTest (IdentityT m) where+  liftTest =+    lift . liftTest -writeLog :: Monad m => Log -> Test m ()-writeLog =-  Test . lift . tell . pure+instance MonadTest m => MonadTest (MaybeT m) where+  liftTest =+    lift . liftTest --- | Generates a random input for the test by running the provided generator.----forAll :: (Monad m, Show a, HasCallStack) => Gen m a -> Test m a-forAll gen =-  withFrozenCallStack $ forAllWith showPretty gen+instance MonadTest m => MonadTest (ExceptT x m) where+  liftTest =+    lift . liftTest --- | Generates a random input for the test by running the provided generator.+instance MonadTest m => MonadTest (ReaderT r m) where+  liftTest =+    lift . liftTest++instance MonadTest m => MonadTest (Lazy.StateT s m) where+  liftTest =+    lift . liftTest++instance MonadTest m => MonadTest (Strict.StateT s m) where+  liftTest =+    lift . liftTest++instance (MonadTest m, Monoid w) => MonadTest (Lazy.WriterT w m) where+  liftTest =+    lift . liftTest++instance (MonadTest m, Monoid w) => MonadTest (Strict.WriterT w m) where+  liftTest =+    lift . liftTest++instance (MonadTest m, Monoid w) => MonadTest (Lazy.RWST r w s m) where+  liftTest =+    lift . liftTest++instance (MonadTest m, Monoid w) => MonadTest (Strict.RWST r w s m) where+  liftTest =+    lift . liftTest++instance MonadTest m => MonadTest (ContT r m) where+  liftTest =+    lift . liftTest++instance MonadTest m => MonadTest (ResourceT m) where+  liftTest =+    lift . liftTest++mkTestT :: m (Either Failure a, [Log]) -> TestT m a+mkTestT =+  TestT . ExceptT . Lazy.WriterT++mkTest :: (Either Failure a, [Log]) -> Test a+mkTest =+  mkTestT . Identity++runTestT :: TestT m a -> m (Either Failure a, [Log])+runTestT =+  Lazy.runWriterT . runExceptT . unTest++runTest :: Test a -> (Either Failure a, [Log])+runTest =+  runIdentity . runTestT++-- | Log some information which might be relevant to a potential test failure. -----   /This is a the same as 'forAll' but allows the user to provide a custom/---   /rendering function. This is useful for values which don't have a/---   /'Show' instance./+writeLog :: MonadTest m => Log -> m ()+writeLog x =+  liftTest $ mkTest (pure (), [x])++-- | Fail the test with an error message, useful for building other failure+--   combinators. ---forAllWith :: (Monad m, HasCallStack) => (a -> String) -> Gen m a -> Test m a-forAllWith render gen = do-  x <- Test . lift $ lift gen-  withFrozenCallStack $ annotate (render x)-  return x+failWith :: (MonadTest m, HasCallStack) => Maybe Diff -> String -> m a+failWith diff msg =+  liftTest $ mkTest (Left $ Failure (getCaller callStack) msg diff, [])  -- | Annotates the source code with a message that might be useful for --   debugging a test failure. ---annotate :: (Monad m, HasCallStack) => String -> Test m ()+annotate :: (MonadTest m, HasCallStack) => String -> m () annotate x = do   writeLog $ Annotation (getCaller callStack) x  -- | Annotates the source code with a value that might be useful for --   debugging a test failure. ---annotateShow :: (Monad m, Show a, HasCallStack) => a -> Test m ()+annotateShow :: (MonadTest m, Show a, HasCallStack) => a -> m () annotateShow x = do   withFrozenCallStack $ annotate (showPretty x)  -- | Logs a message to be displayed as additional information in the footer of --   the failure report. ---footnote :: Monad m => String -> Test m ()+footnote :: MonadTest m => String -> m () footnote =   writeLog . Footnote  -- | Logs a value to be displayed as additional information in the footer of --   the failure report. ---footnoteShow :: (Monad m, Show a) => a -> Test m ()+footnoteShow :: (MonadTest m, Show a) => a -> m () footnoteShow =   writeLog . Footnote . showPretty --- | Discards a test entirely.+-- | Fails with an error which shows the difference between two values. ---discard :: Monad m => Test m a-discard =-  Test . lift $ lift Gen.discard+failDiff :: (MonadTest m, Show a, Show b, HasCallStack) => a -> b -> m ()+failDiff x y =+  case valueDiff <$> mkValue x <*> mkValue y of+    Nothing ->+      withFrozenCallStack $+        failWith Nothing $ unlines [+            "━━━ Not Equal ━━━"+          , showPretty x+          , showPretty y+          ]+    Just diff ->+      withFrozenCallStack $+        failWith (Just $ Diff "Failed (" "- lhs" "=/=" "+ rhs" ")" diff) "" --- | Fail with an error message, useful for building other failure combinators.+-- | Fails with an error which renders the type of an exception and its error+--   message. ---failWith :: (Monad m, HasCallStack) => Maybe Diff -> String -> Test m a-failWith diff msg =-  Test . ExceptT . pure . Left $ Failure (getCaller callStack) msg diff+failException :: (MonadTest m, HasCallStack) => SomeException -> m a+failException (SomeException x) =+  withFrozenCallStack $+    failWith Nothing $ unlines [+        "━━━ Exception: " ++ show (typeOf x) ++ " ━━━"+      , List.dropWhileEnd Char.isSpace (displayException x)+      ]  -- | Causes a test to fail. ---failure :: (Monad m, HasCallStack) => Test m a+failure :: (MonadTest m, HasCallStack) => m a failure =   withFrozenCallStack $ failWith Nothing ""  -- | Another name for @pure ()@. ---success :: Monad m => Test m ()+success :: MonadTest m => m () success =-  Test $ pure ()+  pure ()  -- | Fails the test if the condition provided is 'False'. ---assert :: (Monad m, HasCallStack) => Bool -> Test m ()-assert b =-  if b then+assert :: (MonadTest m, HasCallStack) => Bool -> m ()+assert b = do+  ok <- withFrozenCallStack $ eval b+  if ok then     success   else     withFrozenCallStack failure@@ -440,28 +543,44 @@  -- | Fails the test if the two arguments provided are not equal. ---(===) :: (Monad m, Eq a, Show a, HasCallStack) => a -> a -> Test m ()-(===) x y =-  if x == y then+(===) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m ()+(===) x y = do+  ok <- withFrozenCallStack $ eval (x == y)+  if ok then     success   else-    case valueDiff <$> mkValue x <*> mkValue y of-      Nothing ->-        withFrozenCallStack $-          failWith Nothing $ unlines [-              "━━━ Not Equal ━━━"-            , showPretty x-            , showPretty y-            ]-      Just diff ->-        withFrozenCallStack $-          failWith (Just $ Diff "Failed (" "- lhs" "=/=" "+ rhs" ")" diff) ""+    withFrozenCallStack $ failDiff x y +-- | Fails the test if the value throws an exception when evaluated to weak+--   head normal form (WHNF).+--+eval :: (MonadTest m, HasCallStack) => a -> m a+eval x =+  either (withFrozenCallStack failException) pure (tryEvaluate x)++-- | Fails the test if the action throws an exception.+--+--   /The benefit of using this over simply letting the exception bubble up is/+--   /that the location of the closest 'evalM' will be shown in the output./+--+evalM :: (MonadTest m, MonadCatch m, HasCallStack) => m a -> m a+evalM m =+  either (withFrozenCallStack failException) pure =<< tryAll m++-- | Fails the test if the 'IO' action throws an exception.+--+--   /The benefit of using this over 'liftIO' is that the location of the/+--   /exception will be shown in the output./+--+evalIO :: (MonadTest m, MonadIO m, HasCallStack) => IO a -> m a+evalIO m =+  either (withFrozenCallStack failException) pure =<< liftIO (tryAll m)+ -- | Fails the test if the 'Either' is 'Left', otherwise returns the value in --   the 'Right'. ---liftEither :: (Monad m, Show x, HasCallStack) => Either x a -> Test m a-liftEither = \case+evalEither :: (MonadTest m, Show x, HasCallStack) => Either x a -> m a+evalEither = \case   Left x ->     withFrozenCallStack $ failWith Nothing $ showPretty x   Right x ->@@ -470,63 +589,190 @@ -- | Fails the test if the 'ExceptT' is 'Left', otherwise returns the value in --   the 'Right'. ---liftExceptT :: (Monad m, Show x, HasCallStack) => ExceptT x m a -> Test m a-liftExceptT m =-  withFrozenCallStack liftEither =<< lift (runExceptT m)+evalExceptT :: (MonadTest m, Show x, HasCallStack) => ExceptT x m a -> m a+evalExceptT m =+  withFrozenCallStack evalEither =<< runExceptT m --- | Fails the test if the action throws an exception.+------------------------------------------------------------------------+-- PropertyT++instance MonadTrans PropertyT where+  lift =+    PropertyT . lift . lift++instance MFunctor PropertyT where+  hoist f =+    PropertyT . hoist (hoist f) . unPropertyT++instance Distributive PropertyT where+  type Transformer t PropertyT m = (+      Transformer t GenT m+    , Transformer t TestT (GenT m)+    )++  distribute =+    hoist PropertyT .+    distribute .+    hoist distribute .+    unPropertyT++instance PrimMonad m => PrimMonad (PropertyT m) where+  type PrimState (PropertyT m) =+    PrimState m+  primitive =+    lift . primitive++---- FIXME instance MonadWriter w m => MonadWriter w (PropertyT m)++instance Monad m => MonadTest (PropertyT m) where+  liftTest =+    PropertyT . hoist (pure . runIdentity)++instance MonadPlus m => MonadPlus (PropertyT m) where+  mzero =+    discard++  mplus (PropertyT x) (PropertyT y) =+    PropertyT . mkTestT $+      mplus (runTestT x) (runTestT y)++instance MonadPlus m => Alternative (PropertyT m) where+  empty =+    mzero+  (<|>) =+    mplus++-- | Generates a random input for the test by running the provided generator. -----   /The benefit of using this over 'lift' is that the location of the---   exception will be shown in the output./+--   /This is a the same as 'forAllT' but allows the user to provide a custom/+--   /rendering function. This is useful for values which don't have a/+--   /'Show' instance./ ---liftCatch :: (MonadCatch m, HasCallStack) => m a -> Test m a-liftCatch m =-  withFrozenCallStack liftEither =<< lift (tryAll m)+forAllWithT :: (Monad m, HasCallStack) => (a -> String) -> GenT m a -> PropertyT m a+forAllWithT render gen = do+  x <- PropertyT $ lift gen+  withFrozenCallStack $ annotate (render x)+  return x --- | Fails the test if the action throws an exception.+-- | Generates a random input for the test by running the provided generator. -----   /The benefit of using this over 'liftIO' is that the location of the---   exception will be shown in the output./+--   /This is a the same as 'forAll' but allows the user to provide a custom/+--   /rendering function. This is useful for values which don't have a/+--   /'Show' instance./ ---liftCatchIO :: (MonadIO m, HasCallStack) => IO a -> Test m a-liftCatchIO m =-  withFrozenCallStack liftEither =<< liftIO (tryAll m)+forAllWith :: (Monad m, HasCallStack) => (a -> String) -> Gen a -> PropertyT m a+forAllWith render gen =+  withFrozenCallStack $ forAllWithT render $ Gen.lift gen --- | Fails the test if the 'ExceptT' is 'Left', otherwise returns the value in---   the 'Right'.+-- | Generates a random input for the test by running the provided generator. ---withExceptT :: (Monad m, Show x, HasCallStack) => Test (ExceptT x m) a -> Test m a-withExceptT m =-  withFrozenCallStack liftEither =<< runExceptT (distribute m)+forAllT :: (Monad m, Show a, HasCallStack) => GenT m a -> PropertyT m a+forAllT gen =+  withFrozenCallStack $ forAllWithT showPretty gen --- | Fails the test if the action throws an exception.+-- | Generates a random input for the test by running the provided generator. -----   /The benefit of using this over simply letting the exception bubble up is---   that the location of the closest 'withCatch' will be shown in the output./+forAll :: (Monad m, Show a, HasCallStack) => Gen a -> PropertyT m a+forAll gen =+  withFrozenCallStack $ forAllWith showPretty gen++-- | Discards the current test entirely. ---withCatch :: (MonadCatch m, HasCallStack) => Test m a -> Test m a-withCatch m =-  withFrozenCallStack liftEither =<< tryAll m+discard :: Monad m => PropertyT m a+discard =+  PropertyT $ lift Gen.discard --- | Run a computation which requires resource acquisition / release.+-- | Lift a test in to a property. -----   /Note that if you 'Control.Monad.Trans.Resource.allocate' anything before/---   /a 'forAll' you will likely encounter unexpected behaviour, due to the way/---   /'ResourceT' interacts with the control flow introduced by shrinking./+--   Because both 'TestT' and 'PropertyT' have 'MonadTest' instances, this+--   function is not often required. It can however be useful for writing+--   functions directly in 'TestT' and thus gaining a 'MonadTransControl'+--   instance at the expense of not being able to generate additional inputs+--   using 'forAll'. ---withResourceT :: MonadResourceBase m => Test (ResourceT m) a -> Test m a-withResourceT =-  hoist runResourceT+--   One use case for this is writing tests which use 'ResourceT':+--+-- @+--   property $ do+--     n <- forAll $ Gen.int64 Range.linearBounded+--     test . runResourceT $ do+--       -- test with resource usage here+-- @+--+test :: Monad m => TestT m a -> PropertyT m a+test =+  PropertyT . hoist lift  ------------------------------------------------------------------------+-- Property++-- | The default configuration for a property test.+--+defaultConfig :: PropertyConfig+defaultConfig =+  PropertyConfig {+      propertyTestLimit =+        100+    , propertyDiscardLimit =+        100+    , propertyShrinkLimit =+        1000+    , propertyShrinkRetries =+        0+    }++-- | Map a config modification function over a property.+--+mapConfig :: (PropertyConfig -> PropertyConfig) -> Property -> Property+mapConfig f (Property cfg t) =+  Property (f cfg) t++-- | Set the number times a property should be executed before it is considered+--   successful.+--+withTests :: TestLimit -> Property -> Property+withTests n =+  mapConfig $ \config -> config { propertyTestLimit = n }++-- | Set the number times a property is allowed to discard before the test+--   runner gives up.+--+withDiscards :: DiscardLimit -> Property -> Property+withDiscards n =+  mapConfig $ \config -> config { propertyDiscardLimit = n }++-- | Set the number times a property is allowed to shrink before the test+--   runner gives up and prints the counterexample.+--+withShrinks :: ShrinkLimit -> Property -> Property+withShrinks n =+  mapConfig $ \config -> config { propertyShrinkLimit = n }++-- | Set the number times a property will be executed for each shrink before+--   the test runner gives up and tries a different shrink. See 'ShrinkRetries'+--   for more information.+--+withRetries :: ShrinkRetries -> Property -> Property+withRetries n =+  mapConfig $ \config -> config { propertyShrinkRetries = n }++-- | Creates a property with the default configuration.+--+property :: HasCallStack => PropertyT IO () -> Property+property m =+  Property defaultConfig $+    withFrozenCallStack (evalM m)++------------------------------------------------------------------------ -- FIXME Replace with DeriveLift when we drop 7.10 support.  $(deriveLift ''GroupName) $(deriveLift ''PropertyName) $(deriveLift ''PropertyConfig) $(deriveLift ''TestLimit)-$(deriveLift ''ShrinkLimit) $(deriveLift ''DiscardLimit)+$(deriveLift ''ShrinkLimit)+$(deriveLift ''ShrinkRetries)  ------------------------------------------------------------------------ -- Internal
src/Hedgehog/Internal/Queue.hs view
@@ -6,7 +6,7 @@    , runTasks   , finalizeTask- +   , runActiveFinalizers   , dequeueMVar 
src/Hedgehog/Internal/Region.hs view
@@ -1,8 +1,8 @@ module Hedgehog.Internal.Region (     Region(..)   , newEmptyRegion-  , newRegion-  , forceRegion+  , newOpenRegion+  , openRegion   , setRegion   , displayRegions   , displayRegion@@ -10,7 +10,7 @@   , finishRegion   ) where -import           Control.Concurrent.STM (STM, TVar, atomically)+import           Control.Concurrent.STM (STM, TVar) import qualified Control.Concurrent.STM.TMVar as TMVar import qualified Control.Concurrent.STM.TVar as TVar import           Control.Monad.Catch (MonadMask(..), bracket)@@ -20,59 +20,61 @@ import qualified System.Console.Regions as Console  +data Body =+    Empty+  | Open ConsoleRegion+  | Closed+ newtype Region =   Region {-      unRegion :: TVar (Maybe ConsoleRegion)+      unRegion :: TVar Body     }  newEmptyRegion :: LiftRegion m => m Region newEmptyRegion =   liftRegion $ do-    ref <- TVar.newTVar Nothing+    ref <- TVar.newTVar Empty     pure $ Region ref -newRegion :: LiftRegion m => m Region-newRegion =+newOpenRegion :: LiftRegion m => m Region+newOpenRegion =   liftRegion $ do     region <- Console.openConsoleRegion Linear-    ref <- TVar.newTVar $ Just region+    ref <- TVar.newTVar $ Open region     pure $ Region ref -forceRegion :: LiftRegion m => Region -> String -> m ()-forceRegion (Region var) content =+openRegion :: LiftRegion m => Region -> String -> m ()+openRegion (Region var) content =   liftRegion $ do-    mregion <- TVar.readTVar var-    case mregion of-      Nothing -> do+    body <- TVar.readTVar var+    case body of+      Empty -> do         region <- Console.openConsoleRegion Linear-        TVar.writeTVar var $ Just region+        TVar.writeTVar var $ Open region         Console.setConsoleRegion region content -      Just region ->+      Open region ->         Console.setConsoleRegion region content +      Closed ->+        pure ()+ setRegion :: LiftRegion m => Region -> String -> m () setRegion (Region var) content =   liftRegion $ do-    mregion <- TVar.readTVar var-    case mregion of-      Nothing -> do+    body <- TVar.readTVar var+    case body of+      Empty ->         pure () -      Just region ->+      Open region ->         Console.setConsoleRegion region content -displayRegions :: (MonadIO m, MonadMask m) => m a -> m a-displayRegions io = do-  liftIO . atomically $ do-    -- clear old regions-    mxs <- TMVar.tryTakeTMVar Console.regionList-    case mxs of-      Nothing ->+      Closed ->         pure ()-      Just _xs ->-        TMVar.putTMVar Console.regionList [] +displayRegions :: (MonadIO m, MonadMask m) => m a -> m a+displayRegions io =   Console.displayConsoleRegions io  displayRegion ::@@ -82,29 +84,44 @@   => (Region -> m a)   -> m a displayRegion =-  displayRegions . bracket newRegion finishRegion+  displayRegions . bracket newOpenRegion finishRegion -moveToBottom :: ConsoleRegion -> STM ()-moveToBottom region = do-  mxs <- TMVar.tryTakeTMVar Console.regionList-  case mxs of-    Nothing ->-      pure ()-    Just xs0 ->-      let-        xs1 =-          filter (/= region) xs0-      in-        TMVar.putTMVar Console.regionList (region : xs1)+moveToBottom :: Region -> STM ()+moveToBottom (Region var) =+  liftRegion $ do+    body <- TVar.readTVar var+    case body of+      Empty ->+        pure () +      Open region -> do+        mxs <- TMVar.tryTakeTMVar Console.regionList+        case mxs of+          Nothing ->+            pure ()++          Just xs0 ->+            let+              xs1 =+                filter (/= region) xs0+            in+              TMVar.putTMVar Console.regionList (region : xs1)++      Closed ->+        pure ()+ finishRegion :: LiftRegion m => Region -> m () finishRegion (Region var) =   liftRegion $ do-    mregion <- TVar.readTVar var-    case mregion of-      Nothing ->-        pure ()+    body <- TVar.readTVar var+    case body of+      Empty -> do+        TVar.writeTVar var Closed -      Just region -> do+      Open region -> do         content <- Console.getConsoleRegion region         Console.finishConsoleRegion region content+        TVar.writeTVar var Closed++      Closed ->+        pure ()
src/Hedgehog/Internal/Runner.hs view
@@ -29,11 +29,11 @@ import           Data.Semigroup ((<>))  import           Hedgehog.Internal.Config-import           Hedgehog.Internal.Gen (runGen, runDiscardEffect)+import           Hedgehog.Internal.Gen (runGenT, runDiscardEffect) import           Hedgehog.Internal.Property (Group(..), GroupName(..)) import           Hedgehog.Internal.Property (Property(..), PropertyConfig(..), PropertyName(..))-import           Hedgehog.Internal.Property (ShrinkLimit, withTests)-import           Hedgehog.Internal.Property (Test, Log(..), Failure(..), runTest)+import           Hedgehog.Internal.Property (ShrinkLimit, ShrinkRetries, withTests)+import           Hedgehog.Internal.Property (PropertyT(..), Log(..), Failure(..), runTestT) import           Hedgehog.Internal.Queue import           Hedgehog.Internal.Region import           Hedgehog.Internal.Report@@ -44,10 +44,7 @@  import           Language.Haskell.TH.Lift (deriveLift) -import           System.Console.Regions (ConsoleRegion, RegionLayout(..))-import qualified System.Console.Regions as Console - -- | Configuration for a property test run. -- data RunnerConfig =@@ -85,16 +82,33 @@   _ ->     False +isSuccess :: Node m (Maybe (Either x a, b)) -> Bool+isSuccess =+  not . isFailure++runTreeN ::+     Monad m+  => ShrinkRetries+  -> Tree m (Maybe (Either x a, b))+  -> m (Node m (Maybe (Either x a, b)))+runTreeN n m = do+  o <- runTree m+  if n > 0 && isSuccess o then+    runTreeN (n - 1) m+  else+    pure o+ takeSmallest ::      MonadIO m   => Size   -> Seed   -> ShrinkCount   -> ShrinkLimit+  -> ShrinkRetries   -> (Progress -> m ())   -> Node m (Maybe (Either Failure (), [Log]))   -> m Result-takeSmallest size seed shrinks slimit updateUI = \case+takeSmallest size seed shrinks slimit retries updateUI = \case   Node Nothing _ ->     pure GaveUp @@ -112,9 +126,9 @@           pure $ Failed failure         else           findM xs (Failed failure) $ \m -> do-            o <- runTree m+            o <- runTreeN retries m             if isFailure o then-              Just <$> takeSmallest size seed (shrinks + 1) slimit updateUI o+              Just <$> takeSmallest size seed (shrinks + 1) slimit retries updateUI o             else               return Nothing @@ -128,7 +142,7 @@   => PropertyConfig   -> Size   -> Seed-  -> Test m ()+  -> PropertyT m ()   -> (Report Progress -> m ())   -> m (Report Result) checkReport cfg size0 seed0 test0 updateUI =@@ -156,7 +170,7 @@         case Seed.split seed of           (s0, s1) -> do             node@(Node x _) <--              runTree . runDiscardEffect $ runGen size s0 (runTest test)+              runTree . runDiscardEffect $ runGenT size s0 . runTestT $ unPropertyT test             case x of               Nothing ->                 loop tests (discards + 1) (size + 1) s1@@ -172,6 +186,7 @@                       seed                       0                       (propertyShrinkLimit cfg)+                      (propertyShrinkRetries cfg)                       (updateUI . mkReport)                       node @@ -198,14 +213,14 @@           Running ->             setRegion region ppprogress           Shrinking _ ->-            forceRegion region ppprogress+            openRegion region ppprogress      ppresult <- renderResult mcolor name result     case reportStatus result of       Failed _ ->-        forceRegion region ppresult+        openRegion region ppresult       GaveUp ->-        forceRegion region ppresult+        openRegion region ppresult       OK ->         setRegion region ppresult @@ -258,10 +273,10 @@       summaryFailed summary == 0 &&       summaryGaveUp summary == 0 -updateSummary :: ConsoleRegion -> TVar Summary -> Maybe UseColor -> (Summary -> Summary) -> IO ()+updateSummary :: Region -> TVar Summary -> Maybe UseColor -> (Summary -> Summary) -> IO () updateSummary sregion svar mcolor f = do   summary <- atomically (TVar.modifyTVar' svar f >> TVar.readTVar svar)-  Console.setConsoleRegion sregion =<< renderSummary mcolor summary+  setRegion sregion =<< renderSummary mcolor summary  checkGroupWith ::      WorkerCount@@ -270,8 +285,7 @@   -> [(PropertyName, Property)]   -> IO Summary checkGroupWith n verbosity mcolor props =-  displayRegions $ do-    sregion <- Console.openConsoleRegion Linear+  displayRegion $ \sregion -> do     svar <- atomically . TVar.newTVar $ mempty { summaryWaiting = PropertyCount (length props) }      let@@ -290,7 +304,7 @@                 Quiet ->                   newEmptyRegion                 Normal ->-                  newRegion+                  newOpenRegion              moveToBottom sregion @@ -314,8 +328,6 @@           pure result      updateSummary sregion svar mcolor (const summary)-    Console.finishConsoleRegion sregion =<< Console.getConsoleRegion sregion-     pure summary  -- | Check a group of properties sequentially.
src/Hedgehog/Internal/State.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE DoAndIfThenElse #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-}@@ -14,8 +15,12 @@ module Hedgehog.Internal.State (   -- * Variables     Var(..)-  , Symbolic(..)+  , concrete+  , opaque+   , Concrete(..)+  , Symbolic(..)+  , Name(..)    -- * Environment   , Environment(..)@@ -33,49 +38,60 @@    -- * Actions   , Action(..)+  , Sequential(..)+  , Parallel(..)   , takeVariables   , variablesOK   , dropInvalid   , action-  , actions-  , execute+  , sequential+  , parallel   , executeSequential+  , executeParallel   ) where -import           Control.Monad (when, foldM_)+import qualified Control.Concurrent.Async.Lifted as Async+import           Control.Monad (foldM, foldM_) import           Control.Monad.Catch (MonadCatch)-import           Control.Monad.Morph (hoist)-import           Control.Monad.State.Class (get, put, modify)+import           Control.Monad.State.Class (MonadState, get, put, modify) import           Control.Monad.Trans.Class (lift)-import           Control.Monad.Trans.State (StateT, execState, evalStateT)+import           Control.Monad.Trans.Control (MonadBaseControl)+import           Control.Monad.Trans.State (State, runState, execState)+import           Control.Monad.Trans.State (StateT(..), evalStateT)  import           Data.Dynamic (Dynamic, toDyn, fromDynamic, dynTypeRep) import           Data.Foldable (traverse_)-import           Data.Functor.Classes (Eq1(..), Ord1(..), Show1(..), showsPrec1)+import           Data.Functor.Classes (Eq1(..), Ord1(..), Show1(..))+import           Data.Functor.Classes (eq1, compare1, showsPrec1) import           Data.Map (Map) import qualified Data.Map as Map import qualified Data.Maybe as Maybe import           Data.Typeable (Typeable, TypeRep, Proxy(..), typeRep) -import           Hedgehog.Internal.Gen (Gen)+import           Hedgehog.Internal.Gen (MonadGen) import qualified Hedgehog.Internal.Gen as Gen import           Hedgehog.Internal.HTraversable (HTraversable(..))-import           Hedgehog.Internal.Property (Test, liftEither, withCatch, success)-import qualified Hedgehog.Internal.Shrink as Shrink-import           Hedgehog.Internal.Source (HasCallStack, withFrozenCallStack)+import           Hedgehog.Internal.Opaque (Opaque(..))+import           Hedgehog.Internal.Property (MonadTest(..), Test, evalEither, evalM, success, runTest, failWith) import           Hedgehog.Internal.Range (Range)+import           Hedgehog.Internal.Show (showPretty)+import           Hedgehog.Internal.Source (HasCallStack, withFrozenCallStack)   -- | Symbolic variable names. ---newtype Var =-  Var Int-  deriving (Eq, Ord, Show, Num)+newtype Name =+  Name Int+  deriving (Eq, Ord, Num) +instance Show Name where+  showsPrec p (Name x) =+    showsPrec p x+ -- | Symbolic values. -- data Symbolic a where-  Symbolic :: Typeable a => Var -> Symbolic a+  Symbolic :: Typeable a => Name -> Symbolic a  deriving instance Eq (Symbolic a) deriving instance Ord (Symbolic a)@@ -119,19 +135,71 @@     comp x y  ------------------------------------------------------------------------++-- | Variables are the potential or actual result of executing an action. They+--   are parameterised by either `Symbolic` or `Concrete` depending on the+--   phase of the test.+--+--   `Symbolic` variables are the potential results of actions. These are used+--   when generating the sequence of actions to execute. They allow actions+--   which occur later in the sequence to make use of the result of an action+--   which came earlier in the sequence.+--+--   `Concrete` variables are the actual results of actions. These are used+--   during test execution. They provide access to the actual runtime value of+--   a variable.+--+--   The state update `Callback` for a command needs to be polymorphic in the+--   type of variable because it is used in both the generation and the+--   execution phase.+--+data Var a v =+  Var (v a)++-- | Take the value from a concrete variable.+--+concrete :: Var a Concrete -> a+concrete (Var (Concrete x)) =+  x++-- | Take the value from an opaque concrete variable.+--+opaque :: Var (Opaque a) Concrete -> a+opaque (Var (Concrete (Opaque x))) =+  x++instance (Eq a, Eq1 v) => Eq (Var a v) where+  (==) (Var x) (Var y) =+    eq1 x y++instance (Ord a, Ord1 v) => Ord (Var a v) where+  compare (Var x) (Var y) =+    compare1 x y++instance (Show a, Show1 v) => Show (Var a v) where+  showsPrec p (Var x) =+    showParen (p >= 11) $+      showString "Var " .+      showsPrec1 11 x++instance HTraversable (Var a) where+  htraverse f (Var v) =+    fmap Var (f v)++------------------------------------------------------------------------ -- Symbolic Environment  -- | A mapping of symbolic values to concrete values. -- newtype Environment =   Environment {-      unEnvironment :: Map Var Dynamic+      unEnvironment :: Map Name Dynamic     } deriving (Show)  -- | Environment errors. -- data EnvironmentError =-    EnvironmentValueNotFound !Var+    EnvironmentValueNotFound !Name   | EnvironmentTypeError !TypeRep !TypeRep     deriving (Eq, Ord, Show) @@ -179,7 +247,7 @@  -- | Optional command configuration. ---data Callback input output m state =+data Callback input output state =   -- | A pre-condition for a command that must be verified before the command   --   can be executed. This is mainly used during shrinking to ensure that it   --   is still OK to run a command despite the fact that some previously@@ -192,17 +260,20 @@   --   it must work over 'Symbolic' values when we are generating actions, and   --   'Concrete' values when we are executing them.   ---  | Update (forall v. Ord1 v => state v -> input v -> v output -> state v)+  | Update (forall v. Ord1 v => state v -> input v -> Var output v -> state v)    -- | A post-condition for a command that must be verified for the command to   --   be considered a success.   ---  | Ensure (state Concrete -> input Concrete -> output -> Test m ())+  --   This callback receives the state prior to execution as the first+  --   argument, and the state after execution as the second argument.+  --+  | Ensure (state Concrete -> state Concrete -> input Concrete -> output -> Test ())  callbackRequire1 ::      state Symbolic   -> input Symbolic-  -> Callback input output m state+  -> Callback input output state   -> Bool callbackRequire1 s i = \case   Require f ->@@ -216,8 +287,8 @@      Ord1 v   => state v   -> input v-  -> v output-  -> Callback input output m state+  -> Var output v+  -> Callback input output state   -> state v callbackUpdate1 s i o = \case   Require _ ->@@ -228,22 +299,22 @@     s  callbackEnsure1 ::-     Monad m-  => state Concrete+     state Concrete+  -> state Concrete   -> input Concrete   -> output-  -> Callback input output m state-  -> Test m ()-callbackEnsure1 s i o = \case+  -> Callback input output state+  -> Test ()+callbackEnsure1 s0 s i o = \case   Require _ ->     success   Update _ ->     success   Ensure f ->-    f s i o+    f s0 s i o  callbackRequire ::-     [Callback input output m state]+     [Callback input output state]   -> state Symbolic   -> input Symbolic   -> Bool@@ -252,23 +323,23 @@  callbackUpdate ::      Ord1 v-  => [Callback input output m state]+  => [Callback input output state]   -> state v   -> input v-  -> v output+  -> Var output v   -> state v callbackUpdate callbacks s0 i o =   foldl (\s -> callbackUpdate1 s i o) s0 callbacks  callbackEnsure ::-     Monad m-  => [Callback input output m state]+     [Callback input output state]   -> state Concrete+  -> state Concrete   -> input Concrete   -> output-  -> Test m ()-callbackEnsure callbacks s i o =-  traverse_ (callbackEnsure1 s i o) callbacks+  -> Test ()+callbackEnsure callbacks s0 s i o =+  traverse_ (callbackEnsure1 s0 s i o) callbacks  ------------------------------------------------------------------------ @@ -283,18 +354,18 @@     --   'Nothing'.     --       commandGen ::-        state Symbolic -> Maybe (Gen n (input Symbolic))+        state Symbolic -> Maybe (n (input Symbolic))      -- | Executes a command using the arguments generated by 'commandGen'.     --     , commandExecute ::-        input Concrete -> Test m output+        input Concrete -> m output      -- | A set of callbacks which provide optional command configuration such     --   as pre-condtions, post-conditions and state updates.     --     , commandCallbacks ::-        [Callback input output m state]+        [Callback input output state]     }  -- | Checks that input for a command can be executed in the given state.@@ -317,45 +388,46 @@         Symbolic output      , actionExecute ::-        input Concrete -> Test m output+        input Concrete -> m output      , actionRequire ::         state Symbolic -> input Symbolic -> Bool      , actionUpdate ::-        forall v. Ord1 v => state v -> input v -> v output -> state v+        forall v. Ord1 v => state v -> input v -> Var output v -> state v      , actionEnsure ::-        state Concrete -> input Concrete -> output -> Test m ()+        state Concrete -> state Concrete -> input Concrete -> output -> Test ()     }  instance Show (Action m state) where-  showsPrec p (Action input output _ _ _ _) =+  showsPrec p (Action input (Symbolic (Name output)) _ _ _ _) =     showParen (p > 10) $+      showString "Var " .       showsPrec 11 output .       showString " :<- " .       showsPrec 11 input  -- | Extract the variable name and the type from a symbolic value. ---takeSymbolic :: forall a. Symbolic a -> (Var, TypeRep)-takeSymbolic (Symbolic var) =-  (var, typeRep (Proxy :: Proxy a))+takeSymbolic :: forall a. Symbolic a -> (Name, TypeRep)+takeSymbolic (Symbolic name) =+  (name, typeRep (Proxy :: Proxy a))  -- | Insert a symbolic variable in to a map of variables to types. ---insertSymbolic :: Symbolic a -> Map Var TypeRep -> Map Var TypeRep+insertSymbolic :: Symbolic a -> Map Name TypeRep -> Map Name TypeRep insertSymbolic s =   let-    (var, typ) =+    (name, typ) =       takeSymbolic s   in-    Map.insert var typ+    Map.insert name typ  -- | Collects all the symbolic values in a data structure and produces a set of --   all the variables they refer to. ---takeVariables :: forall t. HTraversable t => t Symbolic -> Map Var TypeRep+takeVariables :: forall t. HTraversable t => t Symbolic -> Map Name TypeRep takeVariables xs =   let     go x = do@@ -367,7 +439,7 @@ -- | Checks that the symbolic values in the data structure refer only to the --   variables in the provided set, and that they are of the correct type. ---variablesOK :: HTraversable t => t Symbolic -> Map Var TypeRep -> Bool+variablesOK :: HTraversable t => t Symbolic -> Map Name TypeRep -> Bool variablesOK xs allowed =   let     vars =@@ -376,58 +448,87 @@     Map.null (vars `Map.difference` allowed) &&     and (Map.intersectionWith (==) vars allowed) +data Context state =+  Context {+      contextState :: state Symbolic+    , _contextVars :: Map Name TypeRep+    }++mkContext :: state Symbolic -> Context state+mkContext initial =+  Context initial Map.empty++contextUpdate :: MonadState (Context state) m => state Symbolic -> m ()+contextUpdate state = do+  Context _ vars <- get+  put $ Context state vars++contextNewVar :: (MonadState (Context state) m, Typeable a) => m (Symbolic a)+contextNewVar = do+  Context state vars <- get++  let+    var =+      case Map.maxViewWithKey vars of+        Nothing ->+          Symbolic 0+        Just ((name, _), _) ->+          Symbolic (name + 1)++  put $ Context state (insertSymbolic var vars)+  pure var+ -- | Drops invalid actions from the sequence. ---dropInvalid :: (forall v. state v) -> [Action m state] -> [Action m state]-dropInvalid initial =+dropInvalid :: [Action m state] -> State (Context state) [Action m state]+dropInvalid =   let     loop step@(Action input output _execute require update _ensure) = do-      ((state0, vars0), steps0) <- get+      Context state0 vars0 <- get -      when (require state0 input && variablesOK input vars0) $+      if require state0 input && variablesOK input vars0 then do         let           state =-            update state0 input output+            update state0 input (Var output)            vars =             insertSymbolic output vars0 -          steps =-            steps0 ++ [step]-        in-          put ((state, vars), steps)+        put $ Context state vars+        pure $ Just step+      else+        pure Nothing   in-    snd . flip execState ((initial, Map.empty), []) . traverse_ loop+    fmap Maybe.catMaybes . traverse loop  -- | Generates a single action from a set of possible commands. -- action ::-     (Monad n, Monad m)+     (MonadGen n, MonadTest m)   => [Command n m state]-  -> Gen (StateT (state Symbolic, Var) n) (Action m state)+  -> StateT (Context state) n (Action m state) action commands =   Gen.just $ do-    (state, var) <- get+    Context state0 _ <- get      Command mgenInput exec callbacks <--      Gen.element $ filter (\c -> commandGenOK c state) commands+      Gen.element $ filter (\c -> commandGenOK c state0) commands      input <--      case mgenInput state of+      case mgenInput state0 of         Nothing ->           error "genCommand: internal error, tried to use generator with invalid state."         Just g ->-          hoist lift g+          lift g -    if not $ callbackRequire callbacks state input then+    if not $ callbackRequire callbacks state0 input then       pure Nothing      else do-      let-        output =-          Symbolic var+      output <- contextNewVar -      put (callbackUpdate callbacks state input output, var + 1)+      contextUpdate $+        callbackUpdate callbacks state0 input (Var output)        pure . Just $         Action input output exec@@ -435,31 +536,139 @@           (callbackUpdate callbacks)           (callbackEnsure callbacks) +genActions ::+     (MonadGen n, MonadTest m)+  => Range Int+  -> [Command n m state]+  -> Context state+  -> n ([Action m state], Context state)+genActions range commands ctx = do+  xs <- Gen.list range (action commands) `evalStateT` ctx+  pure $+    dropInvalid xs `runState` ctx++-- | A sequence of actions to execute.+--+data Sequential m state =+  Sequential {+      -- | The sequence of actions.+      sequentialActions :: [Action m state]+    }++renderAction :: Action m state -> [String]+renderAction (Action input (Symbolic (Name output)) _ _ _ _) =+  let+    prefix0 =+      "Var " ++ show output ++ " = "++    prefix =+      replicate (length prefix0) ' '+  in+    case lines (showPretty input) of+      [] ->+        [prefix0 ++ "?"]+      x : xs ->+        (prefix0 ++ x) :+        fmap (prefix ++) xs++-- FIXME we should not abuse Show to get nice output for actions+instance Show (Sequential m state) where+  show (Sequential xs) =+    unlines $ concatMap renderAction xs+ -- | Generates a sequence of actions from an initial model state and set of commands. ---actions ::-     (Monad n, Monad m)+sequential ::+     (MonadGen n, MonadTest m)   => Range Int   -> (forall v. state v)   -> [Command n m state]-  -> Gen n [Action m state]-actions range initial =-  fmap (dropInvalid initial) .-  Gen.shrink Shrink.list .-  hoist (flip evalStateT (initial, 0)) .-  Gen.list range .-  action+  -> n (Sequential m state)+sequential range initial commands =+  fmap (Sequential . fst) $+    genActions range commands (mkContext initial) +-- | A sequential prefix of actions to execute, with two branches to execute in parallel.+--+data Parallel m state =+  Parallel {+      -- | The sequential prefix.+      parallelPrefix :: [Action m state]++      -- | The first branch.+    , parallelBranch1 :: [Action m state]++      -- | The second branch.+    , parallelBranch2 :: [Action m state]+    }++-- FIXME we should not abuse Show to get nice output for actions+instance Show (Parallel m state) where+  show (Parallel pre xs ys) =+    unlines $ concat [+        ["━━━ Prefix ━━━"]+      ,  (concatMap renderAction pre)+      , ["", "━━━ Branch 1 ━━━"]+      ,  (concatMap renderAction xs)+      , ["", "━━━ Branch 2 ━━━"]+      ,  (concatMap renderAction ys)+      ]++-- | Given the initial model state and set of commands, generates prefix+--   actions to be run sequentially, followed by two branches to be run in+--   parallel.+--+parallel ::+     (MonadGen n, MonadTest m)+  => Range Int+  -> Range Int+  -> (forall v. state v)+  -> [Command n m state]+  -> n (Parallel m state)+parallel prefixN parallelN initial commands = do+  (prefix, ctx0) <- genActions prefixN commands (mkContext initial)+  (branch1, ctx1) <- genActions parallelN commands ctx0+  (branch2, _ctx2) <- genActions parallelN commands ctx1 { contextState = contextState ctx0 }++  pure $ Parallel prefix branch1 branch2++data ActionCheck state =+  ActionCheck {+      checkUpdate :: state Concrete -> state Concrete+    , checkEnsure :: state Concrete -> state Concrete -> Test ()+    }++execute :: (MonadTest m, HasCallStack) => Action m state -> StateT Environment m (ActionCheck state)+execute (Action sinput soutput exec _require update ensure) =+  withFrozenCallStack $ do+    env0 <- get+    input <- evalEither $ reify env0 sinput+    output <- lift $ exec input++    let+      coutput =+        Concrete output++      env =+        insertConcrete soutput coutput env0++    put env++    pure $+      ActionCheck+        (\s0 -> update s0 input (Var coutput))+        (\s0 s -> ensure s0 s input output)+ -- | Executes a single action in the given evironment. ---execute ::-     (HasCallStack, Monad m)+executeUpdateEnsure ::+     (MonadTest m, HasCallStack)   => (state Concrete, Environment)   -> Action m state-  -> Test m (state Concrete, Environment)-execute (state0, env0) (Action sinput soutput exec _require update ensure) =+  -> m (state Concrete, Environment)+executeUpdateEnsure (state0, env0) (Action sinput soutput exec _require update ensure) =   withFrozenCallStack $ do-    input <- liftEither $ reify env0 sinput+    input <- evalEither $ reify env0 sinput     output <- exec input      let@@ -467,12 +676,12 @@         Concrete output        state =-        update state0 input coutput+        update state0 input (Var coutput)        env =         insertConcrete soutput coutput env0 -    ensure state input output+    liftTest $ ensure state0 state input output      pure (state, env) @@ -480,14 +689,84 @@ --   post-conditions are met and no exceptions are thrown. -- --   To generate a sequence of actions to execute, see the---   'Hedgehog.Gen.actions' combinator in the "Hedgehog.Gen" module.+--   'Hedgehog.Gen.sequential' combinator in the "Hedgehog.Gen" module. -- executeSequential ::-     forall m state.-     (HasCallStack, MonadCatch m)+     (MonadTest m, MonadCatch m, HasCallStack)   => (forall v. state v)-  -> [Action m state]-  -> Test m ()-executeSequential initial commands =+  -> Sequential m state+  -> m ()+executeSequential initial (Sequential xs) =+  withFrozenCallStack $ evalM $+    foldM_ executeUpdateEnsure (initial, emptyEnvironment) xs++successful :: Test () -> Bool+successful x =+  case runTest x of+    (Left _, _) ->+      False+    (Right _, _) ->+      True++interleave :: [a] -> [a] -> [[a]]+interleave xs00 ys00 =+  case (xs00, ys00) of+    ([], []) ->+      []+    (xs, []) ->+      [xs]+    ([], ys) ->+      [ys]+    (xs0@(x:xs), ys0@(y:ys)) ->+      [ x : zs | zs <- interleave xs ys0 ] +++      [ y : zs | zs <- interleave xs0 ys ]++checkActions :: state Concrete -> [ActionCheck state] -> Test ()+checkActions s0 = \case+  [] ->+    pure ()+  x : xs -> do+    let+      s =+        checkUpdate x s0++    checkEnsure x s0 s+    checkActions s xs++linearize :: MonadTest m => state Concrete -> [ActionCheck state] -> [ActionCheck state] -> m ()+linearize initial branch1 branch2 =   withFrozenCallStack $-    withCatch (foldM_ execute (initial, emptyEnvironment) commands)+    let+      ok =+        any successful .+        fmap (checkActions initial) $+        interleave branch1 branch2+    in+      if ok then+        pure ()+      else+        failWith Nothing "no valid interleaving"+++-- | Executes the prefix actions sequentially, then executes the two branches+--   in parallel, verifying that no exceptions are thrown and that there is at+--   least one sequential interleaving where all the post-conditions are met.+--+--   To generate parallel actions to execute, see the 'Hedgehog.Gen.parallel'+--   combinator in the "Hedgehog.Gen" module.+--+executeParallel ::+     (MonadTest m, MonadCatch m, MonadBaseControl IO m, HasCallStack)+  => (forall v. state v)+  -> Parallel m state+  -> m ()+executeParallel initial (Parallel prefix branch1 branch2) =+  withFrozenCallStack $ evalM $ do+    (s0, env0) <- foldM executeUpdateEnsure (initial, emptyEnvironment) prefix++    (xs, ys) <-+      Async.concurrently+        (evalStateT (traverse execute branch1) env0)+        (evalStateT (traverse execute branch2) env0)++    linearize s0 xs ys
src/Hedgehog/Internal/Tripping.hs view
@@ -10,16 +10,11 @@ -- | Test that a pair of encode / decode functions are compatible. -- tripping ::-     HasCallStack-  => Applicative f-  => Monad m-  => Show b-  => Show (f a)-  => Eq (f a)+     (MonadTest m, Applicative f, Show b, Show (f a), Eq (f a), HasCallStack)   => a   -> (a -> b)   -> (b -> f a)-  -> Test m ()+  -> m () tripping x encode decode =   let     mx =
test/Test/Hedgehog/Text.hs view
@@ -12,11 +12,11 @@ import           Text.Read (readEither)  -genSize :: Monad m => Gen m Size+genSize :: Gen Size genSize =   Size <$> Gen.enumBounded -genOdd :: Monad m => Gen m Int64+genOdd :: Gen Int64 genOdd =   let     mkOdd x =@@ -27,19 +27,19 @@   in     mkOdd <$> Gen.int64 (Range.constant 1 maxBound) -genSeed :: Monad m => Gen m Seed+genSeed :: Gen Seed genSeed =   Seed <$> Gen.enumBounded <*> genOdd -genPrecedence :: Monad m => Gen m Int+genPrecedence :: Gen Int genPrecedence =   Gen.int (Range.constant 0 11) -genString :: Monad m => Gen m String+genString :: Gen String genString =   Gen.string (Range.constant 0 100) Gen.alpha -checkShowAppend :: (Typeable a, Show a) => Gen IO a -> Property+checkShowAppend :: (Typeable a, Show a) => Gen a -> Property checkShowAppend gen =   property $ do     prec <- forAll genPrecedence@@ -48,7 +48,7 @@     ysuffix <- forAll genString     showsPrec prec x xsuffix ++ ysuffix  === showsPrec prec x (xsuffix ++ ysuffix) -trippingReadShow :: (Eq a, Typeable a, Show a, Read a) => Gen IO a -> Property+trippingReadShow :: (Eq a, Typeable a, Show a, Read a) => Gen a -> Property trippingReadShow gen =   property $ do     prec <- forAll genPrecedence