    {-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}
    {-# OPTIONS_GHC -funbox-strict-fields #-}

    -- |
    -- Module      : Criterion.Monad.Internal
    -- Copyright   : (c) 2009 Neil Brown
    --
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- The environment in which most criterion code executes.
    module Criterion.Monad.Internal
        (
          Criterion(..)
        , Crit(..)
        ) where

    import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
    import qualified Control.Monad.Fail as Fail (MonadFail(..))
    import Control.Monad.Reader (MonadReader(..), ReaderT)
    import Control.Monad.Trans (MonadIO)
    import Control.Monad.Trans.Instances ()
    import Criterion.Types (Config)
    import Data.IORef (IORef)
    import Prelude ()
    import Prelude.Compat
    import System.Random.MWC (GenIO)

    data Crit = Crit {
        Crit -> Config
    config   :: !Config
      , Crit -> IORef (Maybe GenIO)
    gen      :: !(IORef (Maybe GenIO))
      }

    -- | The monad in which most criterion code executes.
    newtype Criterion a = Criterion {
          forall a. Criterion a -> ReaderT Crit IO a
    runCriterion :: ReaderT Crit IO a
        } deriving ( (forall a b. (a -> b) -> Criterion a -> Criterion b)
    -> (forall a b. a -> Criterion b -> Criterion a)
    -> Functor Criterion
    forall a b. a -> Criterion b -> Criterion a
    forall a b. (a -> b) -> Criterion a -> Criterion 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 b. (a -> b) -> Criterion a -> Criterion b
    fmap :: forall a b. (a -> b) -> Criterion a -> Criterion b
    $c<$ :: forall a b. a -> Criterion b -> Criterion a
    <$ :: forall a b. a -> Criterion b -> Criterion a
    Functor, Functor Criterion
    Functor Criterion =>
    (forall a. a -> Criterion a)
    -> (forall a b. Criterion (a -> b) -> Criterion a -> Criterion b)
    -> (forall a b c.
        (a -> b -> c) -> Criterion a -> Criterion b -> Criterion c)
    -> (forall a b. Criterion a -> Criterion b -> Criterion b)
    -> (forall a b. Criterion a -> Criterion b -> Criterion a)
    -> Applicative Criterion
    forall a. a -> Criterion a
    forall a b. Criterion a -> Criterion b -> Criterion a
    forall a b. Criterion a -> Criterion b -> Criterion b
    forall a b. Criterion (a -> b) -> Criterion a -> Criterion b
    forall a b c.
    (a -> b -> c) -> Criterion a -> Criterion b -> Criterion 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 -> Criterion a
    pure :: forall a. a -> Criterion a
    $c<*> :: forall a b. Criterion (a -> b) -> Criterion a -> Criterion b
    <*> :: forall a b. Criterion (a -> b) -> Criterion a -> Criterion b
    $cliftA2 :: forall a b c.
    (a -> b -> c) -> Criterion a -> Criterion b -> Criterion c
    liftA2 :: forall a b c.
    (a -> b -> c) -> Criterion a -> Criterion b -> Criterion c
    $c*> :: forall a b. Criterion a -> Criterion b -> Criterion b
    *> :: forall a b. Criterion a -> Criterion b -> Criterion b
    $c<* :: forall a b. Criterion a -> Criterion b -> Criterion a
    <* :: forall a b. Criterion a -> Criterion b -> Criterion a
    Applicative, Applicative Criterion
    Applicative Criterion =>
    (forall a b. Criterion a -> (a -> Criterion b) -> Criterion b)
    -> (forall a b. Criterion a -> Criterion b -> Criterion b)
    -> (forall a. a -> Criterion a)
    -> Monad Criterion
    forall a. a -> Criterion a
    forall a b. Criterion a -> Criterion b -> Criterion b
    forall a b. Criterion a -> (a -> Criterion b) -> Criterion 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 b. Criterion a -> (a -> Criterion b) -> Criterion b
    >>= :: forall a b. Criterion a -> (a -> Criterion b) -> Criterion b
    $c>> :: forall a b. Criterion a -> Criterion b -> Criterion b
    >> :: forall a b. Criterion a -> Criterion b -> Criterion b
    $creturn :: forall a. a -> Criterion a
    return :: forall a. a -> Criterion a
    Monad, Monad Criterion
    Monad Criterion =>
    (forall a. String -> Criterion a) -> MonadFail Criterion
    forall a. String -> Criterion a
    forall (m :: * -> *).
    Monad m =>
    (forall a. String -> m a) -> MonadFail m
    $cfail :: forall a. String -> Criterion a
    fail :: forall a. String -> Criterion a
    Fail.MonadFail, Monad Criterion
    Monad Criterion =>
    (forall a. IO a -> Criterion a) -> MonadIO Criterion
    forall a. IO a -> Criterion a
    forall (m :: * -> *).
    Monad m =>
    (forall a. IO a -> m a) -> MonadIO m
    $cliftIO :: forall a. IO a -> Criterion a
    liftIO :: forall a. IO a -> Criterion a
    MonadIO
                   , Monad Criterion
    Monad Criterion =>
    (forall e a. (HasCallStack, Exception e) => e -> Criterion a)
    -> MonadThrow Criterion
    forall e a. (HasCallStack, Exception e) => e -> Criterion a
    forall (m :: * -> *).
    Monad m =>
    (forall e a. (HasCallStack, Exception e) => e -> m a)
    -> MonadThrow m
    $cthrowM :: forall e a. (HasCallStack, Exception e) => e -> Criterion a
    throwM :: forall e a. (HasCallStack, Exception e) => e -> Criterion a
    MonadThrow, MonadThrow Criterion
    MonadThrow Criterion =>
    (forall e a.
     (HasCallStack, Exception e) =>
     Criterion a -> (e -> Criterion a) -> Criterion a)
    -> MonadCatch Criterion
    forall e a.
    (HasCallStack, Exception e) =>
    Criterion a -> (e -> Criterion a) -> Criterion a
    forall (m :: * -> *).
    MonadThrow m =>
    (forall e a.
     (HasCallStack, Exception e) =>
     m a -> (e -> m a) -> m a)
    -> MonadCatch m
    $ccatch :: forall e a.
    (HasCallStack, Exception e) =>
    Criterion a -> (e -> Criterion a) -> Criterion a
    catch :: forall e a.
    (HasCallStack, Exception e) =>
    Criterion a -> (e -> Criterion a) -> Criterion a
    MonadCatch, MonadCatch Criterion
    MonadCatch Criterion =>
    (forall b.
     HasCallStack =>
     ((forall a. Criterion a -> Criterion a) -> Criterion b)
     -> Criterion b)
    -> (forall b.
        HasCallStack =>
        ((forall a. Criterion a -> Criterion a) -> Criterion b)
        -> Criterion b)
    -> (forall a b c.
        HasCallStack =>
        Criterion a
        -> (a -> ExitCase b -> Criterion c)
        -> (a -> Criterion b)
        -> Criterion (b, c))
    -> MonadMask Criterion
    forall b.
    HasCallStack =>
    ((forall a. Criterion a -> Criterion a) -> Criterion b)
    -> Criterion b
    forall a b c.
    HasCallStack =>
    Criterion a
    -> (a -> ExitCase b -> Criterion c)
    -> (a -> Criterion b)
    -> Criterion (b, c)
    forall (m :: * -> *).
    MonadCatch m =>
    (forall b. HasCallStack => ((forall a. m a -> m a) -> m b) -> m b)
    -> (forall b.
        HasCallStack =>
        ((forall a. m a -> m a) -> m b) -> m b)
    -> (forall a b c.
        HasCallStack =>
        m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c))
    -> MonadMask m
    $cmask :: forall b.
    HasCallStack =>
    ((forall a. Criterion a -> Criterion a) -> Criterion b)
    -> Criterion b
    mask :: forall b.
    HasCallStack =>
    ((forall a. Criterion a -> Criterion a) -> Criterion b)
    -> Criterion b
    $cuninterruptibleMask :: forall b.
    HasCallStack =>
    ((forall a. Criterion a -> Criterion a) -> Criterion b)
    -> Criterion b
    uninterruptibleMask :: forall b.
    HasCallStack =>
    ((forall a. Criterion a -> Criterion a) -> Criterion b)
    -> Criterion b
    $cgeneralBracket :: forall a b c.
    HasCallStack =>
    Criterion a
    -> (a -> ExitCase b -> Criterion c)
    -> (a -> Criterion b)
    -> Criterion (b, c)
    generalBracket :: forall a b c.
    HasCallStack =>
    Criterion a
    -> (a -> ExitCase b -> Criterion c)
    -> (a -> Criterion b)
    -> Criterion (b, c)
    MonadMask )

    instance MonadReader Config Criterion where
        ask :: Criterion Config
    ask     = Crit -> Config
    config (Crit -> Config) -> Criterion Crit -> Criterion Config
    forall a b. (a -> b) -> Criterion a -> Criterion b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` ReaderT Crit IO Crit -> Criterion Crit
    forall a. ReaderT Crit IO a -> Criterion a
    Criterion ReaderT Crit IO Crit
    forall r (m :: * -> *). MonadReader r m => m r
    ask
        local :: forall a. (Config -> Config) -> Criterion a -> Criterion a
    local Config -> Config
    f = ReaderT Crit IO a -> Criterion a
    forall a. ReaderT Crit IO a -> Criterion a
    Criterion (ReaderT Crit IO a -> Criterion a)
    -> (Criterion a -> ReaderT Crit IO a) -> Criterion a -> Criterion a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Crit -> Crit) -> ReaderT Crit IO a -> ReaderT Crit IO a
    forall a. (Crit -> Crit) -> ReaderT Crit IO a -> ReaderT Crit IO a
    forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
    local Crit -> Crit
    fconfig (ReaderT Crit IO a -> ReaderT Crit IO a)
    -> (Criterion a -> ReaderT Crit IO a)
    -> Criterion a
    -> ReaderT Crit IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Criterion a -> ReaderT Crit IO a
    forall a. Criterion a -> ReaderT Crit IO a
    runCriterion
          where fconfig :: Crit -> Crit
    fconfig Crit
    c = Crit
    c { config = f (config c) }