    {-# LANGUAGE CPP #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    module Test.Hspec.Core.Spec.Monad (
    -- RE-EXPORTED from Test.Hspec.Core.Spec
      Spec
    , SpecWith
    , SpecM (SpecM)
    , runSpecM
    , fromSpecList
    , runIO

    , mapSpecForest
    , mapSpecItem
    , mapSpecItem_
    , modifyParams

    , modifyConfig
    -- END RE-EXPORTED from Test.Hspec.Core.Spec

    , Env(..)
    , withEnv
    ) where

    import           Prelude ()
    import           Test.Hspec.Core.Compat

    import           Control.Monad.IO.Class (liftIO)
    import           Control.Monad.Trans.Reader
    import           Control.Monad.Trans.Writer

    import           Test.Hspec.Core.Example
    import           Test.Hspec.Core.Tree

    import           Test.Hspec.Core.Config.Definition (Config)

    -- | A `SpecWith` that can be evaluated directly by the
    -- `Test.Hspec.Core.Runner.hspec` function as it does not require any
    -- parameters.
    type Spec = SpecWith ()

    -- | A @'SpecWith' a@ represents a test or group of tests that require an @a@
    -- value to run.
    --
    -- In the common case, a 'Spec' is a @'SpecWith' ()@ which requires @()@ and
    -- can thus be executed with `Test.Hspec.Core.Runner.hspec'.
    --
    -- To supply an argument to `SpecWith` tests to turn them into `Spec`, use
    -- functions from "Test.Hspec.Core.Hooks" such as
    -- `Test.Hspec.Core.Hooks.around`, `Test.Hspec.Core.Hooks.before',
    -- `Test.Hspec.Core.Hooks.mapSubject' and similar.
    --
    -- Values of this type are created by `Test.Hspec.Core.Spec.it`,
    -- `Test.Hspec.Core.Spec.describe` and similar.
    type SpecWith a = SpecM a ()

    -- |
    -- @since 2.10.0
    modifyConfig :: (Config -> Config) -> SpecWith a
    modifyConfig :: forall a. (Config -> Config) -> SpecWith a
    modifyConfig Config -> Config
    f = WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    -> SpecM a ()
    forall a r.
    WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    SpecM (WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
     -> SpecM a ())
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    -> SpecM a ()
    forall a b. (a -> b) -> a -> b
    $ (Endo Config, [SpecTree a])
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    forall (m :: * -> *) w. Monad m => w -> WriterT w m ()
    tell ((Config -> Config) -> Endo Config
    forall a. (a -> a) -> Endo a
    Endo Config -> Config
    f, [SpecTree a]
    forall a. Monoid a => a
    mempty)

    -- | A writer monad for `SpecTree` forests.
    --
    -- This is used by `Test.Hspec.Core.Spec.describe` and is used
    -- to construct the forest of spec items.
    --
    -- It allows for dynamically generated spec trees, for example, by using data
    -- obtained by performing IO actions with 'runIO'.
    #ifndef __MHS__
    newtype SpecM a r = SpecM { forall a r.
    SpecM a r -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    unSpecM :: WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r }
      deriving ((forall a b. (a -> b) -> SpecM a a -> SpecM a b)
    -> (forall a b. a -> SpecM a b -> SpecM a a) -> Functor (SpecM a)
    forall a b. a -> SpecM a b -> SpecM a a
    forall a b. (a -> b) -> SpecM a a -> SpecM a b
    forall a a b. a -> SpecM a b -> SpecM a a
    forall a a b. (a -> b) -> SpecM a a -> SpecM a b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a a b. (a -> b) -> SpecM a a -> SpecM a b
    fmap :: forall a b. (a -> b) -> SpecM a a -> SpecM a b
    $c<$ :: forall a a b. a -> SpecM a b -> SpecM a a
    <$ :: forall a b. a -> SpecM a b -> SpecM a a
    Functor, Functor (SpecM a)
    Functor (SpecM a) =>
    (forall a. a -> SpecM a a)
    -> (forall a b. SpecM a (a -> b) -> SpecM a a -> SpecM a b)
    -> (forall a b c.
        (a -> b -> c) -> SpecM a a -> SpecM a b -> SpecM a c)
    -> (forall a b. SpecM a a -> SpecM a b -> SpecM a b)
    -> (forall a b. SpecM a a -> SpecM a b -> SpecM a a)
    -> Applicative (SpecM a)
    forall a. Functor (SpecM a)
    forall a. a -> SpecM a a
    forall a a. a -> SpecM a a
    forall a b. SpecM a a -> SpecM a b -> SpecM a a
    forall a b. SpecM a a -> SpecM a b -> SpecM a b
    forall a b. SpecM a (a -> b) -> SpecM a a -> SpecM a b
    forall a a b. SpecM a a -> SpecM a b -> SpecM a a
    forall a a b. SpecM a a -> SpecM a b -> SpecM a b
    forall a a b. SpecM a (a -> b) -> SpecM a a -> SpecM a b
    forall a b c. (a -> b -> c) -> SpecM a a -> SpecM a b -> SpecM a c
    forall a a b c.
    (a -> b -> c) -> SpecM a a -> SpecM a b -> SpecM a c
    forall (f :: * -> *).
    Functor f =>
    (forall a. a -> f a)
    -> (forall a b. f (a -> b) -> f a -> f b)
    -> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
    -> (forall a b. f a -> f b -> f b)
    -> (forall a b. f a -> f b -> f a)
    -> Applicative f
    $cpure :: forall a a. a -> SpecM a a
    pure :: forall a. a -> SpecM a a
    $c<*> :: forall a a b. SpecM a (a -> b) -> SpecM a a -> SpecM a b
    <*> :: forall a b. SpecM a (a -> b) -> SpecM a a -> SpecM a b
    $cliftA2 :: forall a a b c.
    (a -> b -> c) -> SpecM a a -> SpecM a b -> SpecM a c
    liftA2 :: forall a b c. (a -> b -> c) -> SpecM a a -> SpecM a b -> SpecM a c
    $c*> :: forall a a b. SpecM a a -> SpecM a b -> SpecM a b
    *> :: forall a b. SpecM a a -> SpecM a b -> SpecM a b
    $c<* :: forall a a b. SpecM a a -> SpecM a b -> SpecM a a
    <* :: forall a b. SpecM a a -> SpecM a b -> SpecM a a
    Applicative, Applicative (SpecM a)
    Applicative (SpecM a) =>
    (forall a b. SpecM a a -> (a -> SpecM a b) -> SpecM a b)
    -> (forall a b. SpecM a a -> SpecM a b -> SpecM a b)
    -> (forall a. a -> SpecM a a)
    -> Monad (SpecM a)
    forall a. Applicative (SpecM a)
    forall a. a -> SpecM a a
    forall a a. a -> SpecM a a
    forall a b. SpecM a a -> SpecM a b -> SpecM a b
    forall a b. SpecM a a -> (a -> SpecM a b) -> SpecM a b
    forall a a b. SpecM a a -> SpecM a b -> SpecM a b
    forall a a b. SpecM a a -> (a -> SpecM a b) -> SpecM a b
    forall (m :: * -> *).
    Applicative m =>
    (forall a b. m a -> (a -> m b) -> m b)
    -> (forall a b. m a -> m b -> m b)
    -> (forall a. a -> m a)
    -> Monad m
    $c>>= :: forall a a b. SpecM a a -> (a -> SpecM a b) -> SpecM a b
    >>= :: forall a b. SpecM a a -> (a -> SpecM a b) -> SpecM a b
    $c>> :: forall a a b. SpecM a a -> SpecM a b -> SpecM a b
    >> :: forall a b. SpecM a a -> SpecM a b -> SpecM a b
    $creturn :: forall a a. a -> SpecM a a
    return :: forall a. a -> SpecM a a
    Monad)
    #else
    data SpecM a r = SpecM { unSpecM :: WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r }
      deriving Functor

    instance Applicative (SpecM a) where
      pure x = SpecM $ pure x
      SpecM f <*> SpecM x = SpecM $ f <*> x

    instance Monad (SpecM a) where
      SpecM m >>= k = SpecM $ m >>= unSpecM . k
    #endif

    -- | Convert a `Spec` to a forest of `SpecTree`s.
    runSpecM :: SpecWith a -> IO (Endo Config, [SpecTree a])
    runSpecM :: forall a. SpecWith a -> IO (Endo Config, [SpecTree a])
    runSpecM = (ReaderT Env IO (Endo Config, [SpecTree a])
     -> Env -> IO (Endo Config, [SpecTree a]))
    -> Env
    -> ReaderT Env IO (Endo Config, [SpecTree a])
    -> IO (Endo Config, [SpecTree a])
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip ReaderT Env IO (Endo Config, [SpecTree a])
    -> Env -> IO (Endo Config, [SpecTree a])
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    runReaderT ([String] -> Env
    Env []) (ReaderT Env IO (Endo Config, [SpecTree a])
     -> IO (Endo Config, [SpecTree a]))
    -> (SpecWith a -> ReaderT Env IO (Endo Config, [SpecTree a]))
    -> SpecWith a
    -> IO (Endo Config, [SpecTree a])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    -> ReaderT Env IO (Endo Config, [SpecTree a])
    forall (m :: * -> *) w a. Monad m => WriterT w m a -> m w
    execWriterT (WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
     -> ReaderT Env IO (Endo Config, [SpecTree a]))
    -> (SpecWith a
        -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ())
    -> SpecWith a
    -> ReaderT Env IO (Endo Config, [SpecTree a])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SpecWith a
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    forall a r.
    SpecM a r -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    unSpecM

    -- | Create a `Spec` from a forest of `SpecTree`s.
    fromSpecForest :: (Endo Config, [SpecTree a]) -> SpecWith a
    fromSpecForest :: forall a. (Endo Config, [SpecTree a]) -> SpecWith a
    fromSpecForest = WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    -> SpecM a ()
    forall a r.
    WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    SpecM (WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
     -> SpecM a ())
    -> ((Endo Config, [SpecTree a])
        -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ())
    -> (Endo Config, [SpecTree a])
    -> SpecM a ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Endo Config, [SpecTree a])
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) ()
    forall (m :: * -> *) w. Monad m => w -> WriterT w m ()
    tell

    -- | Create a `Spec` from a forest of `SpecTree`s.
    fromSpecList :: [SpecTree a] -> SpecWith a
    fromSpecList :: forall a. [SpecTree a] -> SpecWith a
    fromSpecList = (Endo Config, [SpecTree a]) -> SpecWith a
    forall a. (Endo Config, [SpecTree a]) -> SpecWith a
    fromSpecForest ((Endo Config, [SpecTree a]) -> SpecWith a)
    -> ([SpecTree a] -> (Endo Config, [SpecTree a]))
    -> [SpecTree a]
    -> SpecWith a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (,) Endo Config
    forall a. Monoid a => a
    mempty

    -- | Run an IO action while constructing the spec tree.
    --
    -- `SpecM` is a monad to construct a spec tree, without executing any spec
    -- items itself.  @runIO@ allows you to run IO actions during this construction phase.
    -- The IO action is always run when the spec tree is constructed (e.g. even
    -- when @--dry-run@ is specified).
    -- If you do not need the result of the IO action to construct the spec tree,
    -- `Test.Hspec.Core.Hooks.beforeAll` may be more suitable for your use case.
    runIO :: IO r -> SpecM a r
    runIO :: forall r a. IO r -> SpecM a r
    runIO = WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    forall a r.
    WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    SpecM (WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
     -> SpecM a r)
    -> (IO r -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r)
    -> IO r
    -> SpecM a r
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO r -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    forall a.
    IO a -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO

    mapSpecForest :: ([SpecTree a] -> [SpecTree b]) -> SpecM a r -> SpecM b r
    mapSpecForest :: forall a b r.
    ([SpecTree a] -> [SpecTree b]) -> SpecM a r -> SpecM b r
    mapSpecForest [SpecTree a] -> [SpecTree b]
    f (SpecM WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    specs) = WriterT (Endo Config, [SpecTree b]) (ReaderT Env IO) r -> SpecM b r
    forall a r.
    WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    SpecM ((ReaderT Env IO (r, (Endo Config, [SpecTree a]))
     -> ReaderT Env IO (r, (Endo Config, [SpecTree b])))
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    -> WriterT (Endo Config, [SpecTree b]) (ReaderT Env IO) r
    forall (m :: * -> *) a w (n :: * -> *) b w'.
    (m (a, w) -> n (b, w')) -> WriterT w m a -> WriterT w' n b
    mapWriterT (((r, (Endo Config, [SpecTree a]))
     -> (r, (Endo Config, [SpecTree b])))
    -> ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    -> ReaderT Env IO (r, (Endo Config, [SpecTree b]))
    forall a b. (a -> b) -> ReaderT Env IO a -> ReaderT Env IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (((Endo Config, [SpecTree a]) -> (Endo Config, [SpecTree b]))
    -> (r, (Endo Config, [SpecTree a]))
    -> (r, (Endo Config, [SpecTree b]))
    forall a b. (a -> b) -> (r, a) -> (r, b)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([SpecTree a] -> [SpecTree b])
    -> (Endo Config, [SpecTree a]) -> (Endo Config, [SpecTree b])
    forall b c d. (b -> c) -> (d, b) -> (d, c)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (d, b) (d, c)
    second [SpecTree a] -> [SpecTree b]
    f))) WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    specs)

    -- {-# DEPRECATED mapSpecItem "Use `mapSpecItem_` instead." #-}
    -- | Deprecated: Use `mapSpecItem_` instead.
    mapSpecItem :: (ActionWith a -> ActionWith b) -> (Item a -> Item b) -> SpecWith a -> SpecWith b
    mapSpecItem :: forall a b.
    (ActionWith a -> ActionWith b)
    -> (Item a -> Item b) -> SpecWith a -> SpecWith b
    mapSpecItem ActionWith a -> ActionWith b
    _ = (Item a -> Item b) -> SpecWith a -> SpecWith b
    forall a b. (Item a -> Item b) -> SpecWith a -> SpecWith b
    mapSpecItem_

    mapSpecItem_ :: (Item a -> Item b) -> SpecWith a -> SpecWith b
    mapSpecItem_ :: forall a b. (Item a -> Item b) -> SpecWith a -> SpecWith b
    mapSpecItem_ = ([SpecTree a] -> [SpecTree b]) -> SpecM a () -> SpecM b ()
    forall a b r.
    ([SpecTree a] -> [SpecTree b]) -> SpecM a r -> SpecM b r
    mapSpecForest (([SpecTree a] -> [SpecTree b]) -> SpecM a () -> SpecM b ())
    -> ((Item a -> Item b) -> [SpecTree a] -> [SpecTree b])
    -> (Item a -> Item b)
    -> SpecM a ()
    -> SpecM b ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (IO () -> IO ())
    -> (Item a -> Item b) -> [SpecTree a] -> [SpecTree b]
    forall a b c d. (a -> b) -> (c -> d) -> [Tree a c] -> [Tree b d]
    bimapForest IO () -> IO ()
    forall a. a -> a
    id

    -- | Modifies the `Params` on the spec items to be generated by `SpecWith`.
    modifyParams :: (Params -> Params) -> SpecWith a -> SpecWith a
    modifyParams :: forall a. (Params -> Params) -> SpecWith a -> SpecWith a
    modifyParams Params -> Params
    f = (Item a -> Item a) -> SpecWith a -> SpecWith a
    forall a b. (Item a -> Item b) -> SpecWith a -> SpecWith b
    mapSpecItem_ ((Item a -> Item a) -> SpecWith a -> SpecWith a)
    -> (Item a -> Item a) -> SpecWith a -> SpecWith a
    forall a b. (a -> b) -> a -> b
    $ \Item a
    item -> Item a
    item {itemExample = \Params
    p -> (Item a
    -> Params
    -> (ActionWith a -> IO ())
    -> ProgressCallback
    -> IO Result
    forall a.
    Item a
    -> Params
    -> (ActionWith a -> IO ())
    -> ProgressCallback
    -> IO Result
    itemExample Item a
    item) (Params -> Params
    f Params
    p)}

    newtype Env = Env {
      -- | The path of _parent_ `Hspec.Core.Spec.describe` labels from innermost to
      -- outermost.
      Env -> [String]
    envSpecDescriptionPath :: [String]
    }

    -- | Applies a function to modify the `Env` of items being written by a child
    -- spec writer.
    --
    -- This is used to implement `Hspec.Core.Spec.describe`.
    withEnv :: (Env -> Env) -> SpecM a r -> SpecM a r
    withEnv :: forall a r. (Env -> Env) -> SpecM a r -> SpecM a r
    withEnv Env -> Env
    f = WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    forall a r.
    WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r -> SpecM a r
    SpecM (WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
     -> SpecM a r)
    -> (SpecM a r
        -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r)
    -> SpecM a r
    -> SpecM a r
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
    WriterT (ReaderT Env IO (r, (Endo Config, [SpecTree a]))
     -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r)
    -> (SpecM a r -> ReaderT Env IO (r, (Endo Config, [SpecTree a])))
    -> SpecM a r
    -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Env -> Env)
    -> ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    -> ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    forall r (m :: * -> *) a.
    (r -> r) -> ReaderT r m a -> ReaderT r m a
    local Env -> Env
    f (ReaderT Env IO (r, (Endo Config, [SpecTree a]))
     -> ReaderT Env IO (r, (Endo Config, [SpecTree a])))
    -> (SpecM a r -> ReaderT Env IO (r, (Endo Config, [SpecTree a])))
    -> SpecM a r
    -> ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    -> ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    runWriterT (WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
     -> ReaderT Env IO (r, (Endo Config, [SpecTree a])))
    -> (SpecM a r
        -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r)
    -> SpecM a r
    -> ReaderT Env IO (r, (Endo Config, [SpecTree a]))
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SpecM a r -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    forall a r.
    SpecM a r -> WriterT (Endo Config, [SpecTree a]) (ReaderT Env IO) r
    unSpecM