    -- | Tools for benchmarking and accumulating results.
    --   Nothing Agda-specific in here.

    module Agda.Utils.Benchmark where

    import Prelude hiding (null)

    import Control.DeepSeq
    import qualified Control.Exception as E (evaluate)
    import Control.Monad.Except
    import Control.Monad.Reader
    import Control.Monad.Writer
    import Control.Monad.State
    import Control.Monad.IO.Class ( MonadIO(..) )

    import Data.Function (on)
    import qualified Data.List as List
    import Data.Monoid
    import Data.Maybe

    import GHC.Generics (Generic)

    import qualified Text.PrettyPrint.Boxes as Boxes

    import Agda.Utils.ListT
    import Agda.Utils.Null
    import Agda.Utils.Monad hiding (finally)
    import qualified Agda.Utils.Maybe.Strict as Strict
    import Agda.Syntax.Common.Pretty
    import Agda.Utils.Time
    import Agda.Utils.Trie (Trie)
    import qualified Agda.Utils.Trie as Trie

    -- * Benchmark trie

    -- | Account we can bill computation time to.
    type Account a = [a]

    -- | Record when we started billing the current account.
    type CurrentAccount a = Strict.Maybe (Account a, CPUTime)

    type Timings        a = Trie a CPUTime

    data BenchmarkOn a = BenchmarkOff | BenchmarkOn | BenchmarkSome (Account a -> Bool)
      deriving (forall x. BenchmarkOn a -> Rep (BenchmarkOn a) x)
    -> (forall x. Rep (BenchmarkOn a) x -> BenchmarkOn a)
    -> Generic (BenchmarkOn a)
    forall x. Rep (BenchmarkOn a) x -> BenchmarkOn a
    forall x. BenchmarkOn a -> Rep (BenchmarkOn a) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall a x. Rep (BenchmarkOn a) x -> BenchmarkOn a
    forall a x. BenchmarkOn a -> Rep (BenchmarkOn a) x
    $cfrom :: forall a x. BenchmarkOn a -> Rep (BenchmarkOn a) x
    from :: forall x. BenchmarkOn a -> Rep (BenchmarkOn a) x
    $cto :: forall a x. Rep (BenchmarkOn a) x -> BenchmarkOn a
    to :: forall x. Rep (BenchmarkOn a) x -> BenchmarkOn a
    Generic

    isBenchmarkOn :: Account a -> BenchmarkOn a -> Bool
    isBenchmarkOn :: forall a. Account a -> BenchmarkOn a -> Bool
    isBenchmarkOn Account a
    _ BenchmarkOn a
    BenchmarkOff      = Bool
    False
    isBenchmarkOn Account a
    _ BenchmarkOn a
    BenchmarkOn       = Bool
    True
    isBenchmarkOn Account a
    a (BenchmarkSome Account a -> Bool
    p) = Account a -> Bool
    p Account a
    a

    -- | Benchmark structure is a trie, mapping accounts (phases and subphases)
    --   to CPU time spent on their performance.
    data Benchmark a = Benchmark
      { forall a. Benchmark a -> BenchmarkOn a
    benchmarkOn    :: !(BenchmarkOn a)
        -- ^ Are we benchmarking at all?
      , forall a. Benchmark a -> CurrentAccount a
    currentAccount :: !(CurrentAccount a)
        -- ^ What are we billing to currently?
      , forall a. Benchmark a -> Timings a
    timings        :: !(Timings a)
        -- ^ The accounts and their accumulated timing bill.
      }
      deriving (forall x. Benchmark a -> Rep (Benchmark a) x)
    -> (forall x. Rep (Benchmark a) x -> Benchmark a)
    -> Generic (Benchmark a)
    forall x. Rep (Benchmark a) x -> Benchmark a
    forall x. Benchmark a -> Rep (Benchmark a) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall a x. Rep (Benchmark a) x -> Benchmark a
    forall a x. Benchmark a -> Rep (Benchmark a) x
    $cfrom :: forall a x. Benchmark a -> Rep (Benchmark a) x
    from :: forall x. Benchmark a -> Rep (Benchmark a) x
    $cto :: forall a x. Rep (Benchmark a) x -> Benchmark a
    to :: forall x. Rep (Benchmark a) x -> Benchmark a
    Generic

    -- | Initial benchmark structure (empty).
    instance Null (Benchmark a) where
      empty :: Benchmark a
    empty = Benchmark
        { benchmarkOn :: BenchmarkOn a
    benchmarkOn = BenchmarkOn a
    forall a. BenchmarkOn a
    BenchmarkOff
        , currentAccount :: CurrentAccount a
    currentAccount = CurrentAccount a
    forall a. Maybe a
    Strict.Nothing
        , timings :: Timings a
    timings = Timings a
    forall a. Null a => a
    empty
        }
      null :: Benchmark a -> Bool
    null = Timings a -> Bool
    forall a. Null a => a -> Bool
    null (Timings a -> Bool)
    -> (Benchmark a -> Timings a) -> Benchmark a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Benchmark a -> Timings a
    forall a. Benchmark a -> Timings a
    timings

    -- | Semantic editor combinator.
    mapBenchmarkOn :: (BenchmarkOn a -> BenchmarkOn a) -> Benchmark a -> Benchmark a
    mapBenchmarkOn :: forall a.
    (BenchmarkOn a -> BenchmarkOn a) -> Benchmark a -> Benchmark a
    mapBenchmarkOn BenchmarkOn a -> BenchmarkOn a
    f Benchmark a
    b = Benchmark a
    b { benchmarkOn = f $ benchmarkOn b }

    -- | Semantic editor combinator.
    mapCurrentAccount ::
      (CurrentAccount a -> CurrentAccount a) -> Benchmark a -> Benchmark a
    mapCurrentAccount :: forall a.
    (CurrentAccount a -> CurrentAccount a)
    -> Benchmark a -> Benchmark a
    mapCurrentAccount CurrentAccount a -> CurrentAccount a
    f Benchmark a
    b = Benchmark a
    b { currentAccount = f (currentAccount b) }

    -- | Semantic editor combinator.
    mapTimings :: (Timings a -> Timings a) -> Benchmark a -> Benchmark a
    mapTimings :: forall a. (Timings a -> Timings a) -> Benchmark a -> Benchmark a
    mapTimings Timings a -> Timings a
    f Benchmark a
    b = Benchmark a
    b { timings = f (timings b) }

    -- | Add to specified CPU time account.
    addCPUTime :: Ord a => Account a -> CPUTime -> Benchmark a -> Benchmark a
    addCPUTime :: forall a.
    Ord a =>
    Account a -> CPUTime -> Benchmark a -> Benchmark a
    addCPUTime Account a
    acc CPUTime
    t = (Timings a -> Timings a) -> Benchmark a -> Benchmark a
    forall a. (Timings a -> Timings a) -> Benchmark a -> Benchmark a
    mapTimings ((CPUTime -> CPUTime -> CPUTime)
    -> Account a -> CPUTime -> Timings a -> Timings a
    forall k v.
    Ord k =>
    (v -> v -> v) -> [k] -> v -> Trie k v -> Trie k v
    Trie.insertWith CPUTime -> CPUTime -> CPUTime
    forall a. Num a => a -> a -> a
    (+) Account a
    acc CPUTime
    t)

    -- | Print benchmark as three-column table with totals.
    instance (Ord a, Pretty a) => Pretty (Benchmark a) where
      pretty :: Benchmark a -> Doc
    pretty Benchmark a
    b = [Char] -> Doc
    forall a. [Char] -> Doc a
    text ([Char] -> Doc) -> [Char] -> Doc
    forall a b. (a -> b) -> a -> b
    $ Box -> [Char]
    Boxes.render Box
    table
        where
        trie :: Timings a
    trie = Benchmark a -> Timings a
    forall a. Benchmark a -> Timings a
    timings Benchmark a
    b
        ([[a]]
    accounts, [(CPUTime, CPUTime)]
    times0) = [([a], (CPUTime, CPUTime))] -> ([[a]], [(CPUTime, CPUTime)])
    forall a b. [(a, b)] -> ([a], [b])
    unzip ([([a], (CPUTime, CPUTime))] -> ([[a]], [(CPUTime, CPUTime)]))
    -> [([a], (CPUTime, CPUTime))] -> ([[a]], [(CPUTime, CPUTime)])
    forall a b. (a -> b) -> a -> b
    $ ((CPUTime, CPUTime) -> (CPUTime, CPUTime) -> Ordering)
    -> Trie a (CPUTime, CPUTime) -> [([a], (CPUTime, CPUTime))]
    forall k v. Ord k => (v -> v -> Ordering) -> Trie k v -> [([k], v)]
    Trie.toListOrderedBy ((CPUTime -> CPUTime -> Ordering) -> CPUTime -> CPUTime -> Ordering
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip CPUTime -> CPUTime -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare (CPUTime -> CPUTime -> Ordering)
    -> ((CPUTime, CPUTime) -> CPUTime)
    -> (CPUTime, CPUTime)
    -> (CPUTime, CPUTime)
    -> Ordering
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` (CPUTime, CPUTime) -> CPUTime
    forall a b. (a, b) -> b
    snd)
                                   (Trie a (CPUTime, CPUTime) -> [([a], (CPUTime, CPUTime))])
    -> Trie a (CPUTime, CPUTime) -> [([a], (CPUTime, CPUTime))]
    forall a b. (a -> b) -> a -> b
    $ ((CPUTime, CPUTime) -> Bool)
    -> Trie a (CPUTime, CPUTime) -> Trie a (CPUTime, CPUTime)
    forall k v. Ord k => (v -> Bool) -> Trie k v -> Trie k v
    Trie.filter ((CPUTime -> CPUTime -> Bool
    forall a. Ord a => a -> a -> Bool
    > Integer -> CPUTime
    fromMilliseconds Integer
    10) (CPUTime -> Bool)
    -> ((CPUTime, CPUTime) -> CPUTime) -> (CPUTime, CPUTime) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CPUTime, CPUTime) -> CPUTime
    forall a b. (a, b) -> b
    snd)
                                   (Trie a (CPUTime, CPUTime) -> Trie a (CPUTime, CPUTime))
    -> Trie a (CPUTime, CPUTime) -> Trie a (CPUTime, CPUTime)
    forall a b. (a -> b) -> a -> b
    $ (Timings a -> Maybe (CPUTime, CPUTime))
    -> Timings a -> Trie a (CPUTime, CPUTime)
    forall k u v.
    Ord k =>
    (Trie k u -> Maybe v) -> Trie k u -> Trie k v
    Trie.mapSubTries ((CPUTime, CPUTime) -> Maybe (CPUTime, CPUTime)
    forall a. a -> Maybe a
    Just ((CPUTime, CPUTime) -> Maybe (CPUTime, CPUTime))
    -> (Timings a -> (CPUTime, CPUTime))
    -> Timings a
    -> Maybe (CPUTime, CPUTime)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Timings a -> (CPUTime, CPUTime)
    forall {b} {k}. (Num b, Ord k) => Trie k b -> (b, b)
    aggr) Timings a
    trie
        times :: [CPUTime]
    times = ((CPUTime, CPUTime) -> CPUTime)
    -> [(CPUTime, CPUTime)] -> [CPUTime]
    forall a b. (a -> b) -> [a] -> [b]
    map (CPUTime, CPUTime) -> CPUTime
    forall a b. (a, b) -> a
    fst [(CPUTime, CPUTime)]
    times0
        aggr :: Trie k b -> (b, b)
    aggr Trie k b
    t = (b -> Maybe b -> b
    forall a. a -> Maybe a -> a
    fromMaybe b
    0 (Maybe b -> b) -> Maybe b -> b
    forall a b. (a -> b) -> a -> b
    $ [k] -> Trie k b -> Maybe b
    forall k v. Ord k => [k] -> Trie k v -> Maybe v
    Trie.lookup [] Trie k b
    t, Sum b -> b
    forall a. Sum a -> a
    getSum (Sum b -> b) -> Sum b -> b
    forall a b. (a -> b) -> a -> b
    $ (b -> Sum b) -> Trie k b -> Sum b
    forall m a. Monoid m => (a -> m) -> Trie k a -> m
    forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap b -> Sum b
    forall a. a -> Sum a
    Sum Trie k b
    t)
        aggrTimes :: [Box]
    aggrTimes = do
          (a, (t, aggrT)) <- [[a]] -> [(CPUTime, CPUTime)] -> [([a], (CPUTime, CPUTime))]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [[a]]
    accounts [(CPUTime, CPUTime)]
    times0
          return $ if t == aggrT || null a
                   then ""
                   else Boxes.text $ "(" ++ prettyShow aggrT ++ ")"

        -- Generate a table.
        table :: Box
    table = Int -> Alignment -> [Box] -> Box
    forall (f :: * -> *).
    Foldable f =>
    Int -> Alignment -> f Box -> Box
    Boxes.hsep Int
    1 Alignment
    Boxes.left [Box
    col1, Box
    col2, Box
    col3]

        -- First column: Accounts.
        col1 :: Box
    col1 = Alignment -> [Box] -> Box
    forall (f :: * -> *). Foldable f => Alignment -> f Box -> Box
    Boxes.vcat Alignment
    Boxes.left ([Box] -> Box) -> [Box] -> Box
    forall a b. (a -> b) -> a -> b
    $
               ([Char] -> Box) -> [[Char]] -> [Box]
    forall a b. (a -> b) -> [a] -> [b]
    map [Char] -> Box
    Boxes.text ([[Char]] -> [Box]) -> [[Char]] -> [Box]
    forall a b. (a -> b) -> a -> b
    $
               [Char]
    "Total" [Char] -> [[Char]] -> [[Char]]
    forall a. a -> [a] -> [a]
    : ([a] -> [Char]) -> [[a]] -> [[Char]]
    forall a b. (a -> b) -> [a] -> [b]
    map [a] -> [Char]
    forall {a}. Pretty a => [a] -> [Char]
    showAccount [[a]]
    accounts
        -- Second column: Times.
        col2 :: Box
    col2 = Alignment -> [Box] -> Box
    forall (f :: * -> *). Foldable f => Alignment -> f Box -> Box
    Boxes.vcat Alignment
    Boxes.right ([Box] -> Box) -> [Box] -> Box
    forall a b. (a -> b) -> a -> b
    $
               (CPUTime -> Box) -> [CPUTime] -> [Box]
    forall a b. (a -> b) -> [a] -> [b]
    map ([Char] -> Box
    Boxes.text ([Char] -> Box) -> (CPUTime -> [Char]) -> CPUTime -> Box
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CPUTime -> [Char]
    forall a. Pretty a => a -> [Char]
    prettyShow) ([CPUTime] -> [Box]) -> [CPUTime] -> [Box]
    forall a b. (a -> b) -> a -> b
    $
               [CPUTime] -> CPUTime
    forall a. Num a => [a] -> a
    forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
    sum [CPUTime]
    times CPUTime -> [CPUTime] -> [CPUTime]
    forall a. a -> [a] -> [a]
    : [CPUTime]
    times
        -- Thid column: Aggregate times.
        col3 :: Box
    col3 = Alignment -> [Box] -> Box
    forall (f :: * -> *). Foldable f => Alignment -> f Box -> Box
    Boxes.vcat Alignment
    Boxes.right ([Box] -> Box) -> [Box] -> Box
    forall a b. (a -> b) -> a -> b
    $
               Box
    "" Box -> [Box] -> [Box]
    forall a. a -> [a] -> [a]
    : [Box]
    aggrTimes

        showAccount :: [a] -> [Char]
    showAccount [] = [Char]
    "Miscellaneous"
        showAccount [a]
    ks = [Char] -> [[Char]] -> [Char]
    forall a. [a] -> [[a]] -> [a]
    List.intercalate [Char]
    "." ([[Char]] -> [Char]) -> [[Char]] -> [Char]
    forall a b. (a -> b) -> a -> b
    $ (a -> [Char]) -> [a] -> [[Char]]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> [Char]
    forall a. Pretty a => a -> [Char]
    prettyShow [a]
    ks

    -- * Benchmarking monad.

    -- | Monad with access to benchmarking data.

    class (Ord (BenchPhase m), Functor m, MonadIO m) => MonadBench m where
      type BenchPhase m
      getBenchmark :: m (Benchmark (BenchPhase m))

      putBenchmark :: Benchmark (BenchPhase m) -> m ()
      putBenchmark Benchmark (BenchPhase m)
    b = (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall a b. (a -> b) -> a -> b
    $ Benchmark (BenchPhase m)
    -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    forall a b. a -> b -> a
    const Benchmark (BenchPhase m)
    b

      modifyBenchmark :: (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
      modifyBenchmark Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    f = do
        b <- m (Benchmark (BenchPhase m))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark
        putBenchmark $! f b

      -- | We need to be able to terminate benchmarking in case of an exception.
      finally :: m b -> m c -> m b

      {-# MINIMAL getBenchmark , (putBenchmark | modifyBenchmark) , finally #-}

    getsBenchmark :: MonadBench m => (Benchmark (BenchPhase m) -> c) -> m c
    getsBenchmark :: forall (m :: * -> *) c.
    MonadBench m =>
    (Benchmark (BenchPhase m) -> c) -> m c
    getsBenchmark Benchmark (BenchPhase m) -> c
    f = Benchmark (BenchPhase m) -> c
    f (Benchmark (BenchPhase m) -> c)
    -> m (Benchmark (BenchPhase m)) -> m c
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m (Benchmark (BenchPhase m))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark

    instance MonadBench m => MonadBench (ReaderT r m) where
      type BenchPhase (ReaderT r m) = BenchPhase m
      getBenchmark :: ReaderT r m (Benchmark (BenchPhase (ReaderT r m)))
    getBenchmark    = m (Benchmark (BenchPhase (ReaderT r m)))
    -> ReaderT r m (Benchmark (BenchPhase (ReaderT r m)))
    forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m (Benchmark (BenchPhase (ReaderT r m)))
     -> ReaderT r m (Benchmark (BenchPhase (ReaderT r m))))
    -> m (Benchmark (BenchPhase (ReaderT r m)))
    -> ReaderT r m (Benchmark (BenchPhase (ReaderT r m)))
    forall a b. (a -> b) -> a -> b
    $ m (Benchmark (BenchPhase m))
    m (Benchmark (BenchPhase (ReaderT r m)))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark
      putBenchmark :: Benchmark (BenchPhase (ReaderT r m)) -> ReaderT r m ()
    putBenchmark    = m () -> ReaderT r m ()
    forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> ReaderT r m ())
    -> (Benchmark (BenchPhase m) -> m ())
    -> Benchmark (BenchPhase m)
    -> ReaderT r m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Benchmark (BenchPhase m) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    Benchmark (BenchPhase m) -> m ()
    putBenchmark
      modifyBenchmark :: (Benchmark (BenchPhase (ReaderT r m))
     -> Benchmark (BenchPhase (ReaderT r m)))
    -> ReaderT r m ()
    modifyBenchmark = m () -> ReaderT r m ()
    forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> ReaderT r m ())
    -> ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> ReaderT r m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark
      finally :: forall b c. ReaderT r m b -> ReaderT r m c -> ReaderT r m b
    finally ReaderT r m b
    m ReaderT r m c
    f = (r -> m b) -> ReaderT r m b
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
    ReaderT ((r -> m b) -> ReaderT r m b) -> (r -> m b) -> ReaderT r m b
    forall a b. (a -> b) -> a -> b
    $ \ r
    r ->
        m b -> m c -> m b
    forall b c. m b -> m c -> m b
    forall (m :: * -> *) b c. MonadBench m => m b -> m c -> m b
    finally (ReaderT r m b
    m ReaderT r m b -> r -> m b
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    `runReaderT` r
    r) (ReaderT r m c
    f ReaderT r m c -> r -> m c
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    `runReaderT` r
    r)

    instance (MonadBench m, Monoid w) => MonadBench (WriterT w m) where
      type BenchPhase (WriterT w m) = BenchPhase m
      getBenchmark :: WriterT w m (Benchmark (BenchPhase (WriterT w m)))
    getBenchmark    = m (Benchmark (BenchPhase (WriterT w m)))
    -> WriterT w m (Benchmark (BenchPhase (WriterT w m)))
    forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m (Benchmark (BenchPhase (WriterT w m)))
     -> WriterT w m (Benchmark (BenchPhase (WriterT w m))))
    -> m (Benchmark (BenchPhase (WriterT w m)))
    -> WriterT w m (Benchmark (BenchPhase (WriterT w m)))
    forall a b. (a -> b) -> a -> b
    $ m (Benchmark (BenchPhase m))
    m (Benchmark (BenchPhase (WriterT w m)))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark
      putBenchmark :: Benchmark (BenchPhase (WriterT w m)) -> WriterT w m ()
    putBenchmark    = m () -> WriterT w m ()
    forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> WriterT w m ())
    -> (Benchmark (BenchPhase m) -> m ())
    -> Benchmark (BenchPhase m)
    -> WriterT w m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Benchmark (BenchPhase m) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    Benchmark (BenchPhase m) -> m ()
    putBenchmark
      modifyBenchmark :: (Benchmark (BenchPhase (WriterT w m))
     -> Benchmark (BenchPhase (WriterT w m)))
    -> WriterT w m ()
    modifyBenchmark = m () -> WriterT w m ()
    forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> WriterT w m ())
    -> ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> WriterT w m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark
      finally :: forall b c. WriterT w m b -> WriterT w m c -> WriterT w m b
    finally WriterT w m b
    m WriterT w m c
    f = m (b, w) -> WriterT w m b
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
    WriterT (m (b, w) -> WriterT w m b) -> m (b, w) -> WriterT w m b
    forall a b. (a -> b) -> a -> b
    $ m (b, w) -> m (c, w) -> m (b, w)
    forall b c. m b -> m c -> m b
    forall (m :: * -> *) b c. MonadBench m => m b -> m c -> m b
    finally (WriterT w m b -> m (b, w)
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    runWriterT WriterT w m b
    m) (WriterT w m c -> m (c, w)
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    runWriterT WriterT w m c
    f)

    instance MonadBench m => MonadBench (StateT r m) where
      type BenchPhase (StateT r m) = BenchPhase m

      getBenchmark :: StateT r m (Benchmark (BenchPhase (StateT r m)))
    getBenchmark    = m (Benchmark (BenchPhase (StateT r m)))
    -> StateT r m (Benchmark (BenchPhase (StateT r m)))
    forall (m :: * -> *) a. Monad m => m a -> StateT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m (Benchmark (BenchPhase (StateT r m)))
     -> StateT r m (Benchmark (BenchPhase (StateT r m))))
    -> m (Benchmark (BenchPhase (StateT r m)))
    -> StateT r m (Benchmark (BenchPhase (StateT r m)))
    forall a b. (a -> b) -> a -> b
    $ m (Benchmark (BenchPhase m))
    m (Benchmark (BenchPhase (StateT r m)))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark
      putBenchmark :: Benchmark (BenchPhase (StateT r m)) -> StateT r m ()
    putBenchmark    = m () -> StateT r m ()
    forall (m :: * -> *) a. Monad m => m a -> StateT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> StateT r m ())
    -> (Benchmark (BenchPhase m) -> m ())
    -> Benchmark (BenchPhase m)
    -> StateT r m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Benchmark (BenchPhase m) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    Benchmark (BenchPhase m) -> m ()
    putBenchmark
      modifyBenchmark :: (Benchmark (BenchPhase (StateT r m))
     -> Benchmark (BenchPhase (StateT r m)))
    -> StateT r m ()
    modifyBenchmark = m () -> StateT r m ()
    forall (m :: * -> *) a. Monad m => m a -> StateT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> StateT r m ())
    -> ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> StateT r m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark
      finally :: forall b c. StateT r m b -> StateT r m c -> StateT r m b
    finally StateT r m b
    m StateT r m c
    f = (r -> m (b, r)) -> StateT r m b
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
    StateT ((r -> m (b, r)) -> StateT r m b)
    -> (r -> m (b, r)) -> StateT r m b
    forall a b. (a -> b) -> a -> b
    $ \r
    s ->
        m (b, r) -> m (c, r) -> m (b, r)
    forall b c. m b -> m c -> m b
    forall (m :: * -> *) b c. MonadBench m => m b -> m c -> m b
    finally (StateT r m b
    m StateT r m b -> r -> m (b, r)
    forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
    `runStateT` r
    s) (StateT r m c
    f StateT r m c -> r -> m (c, r)
    forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
    `runStateT` r
    s)

    instance MonadBench m => MonadBench (ExceptT e m) where
      type BenchPhase (ExceptT e m) = BenchPhase m

      getBenchmark :: ExceptT e m (Benchmark (BenchPhase (ExceptT e m)))
    getBenchmark    = m (Benchmark (BenchPhase (ExceptT e m)))
    -> ExceptT e m (Benchmark (BenchPhase (ExceptT e m)))
    forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m (Benchmark (BenchPhase (ExceptT e m)))
     -> ExceptT e m (Benchmark (BenchPhase (ExceptT e m))))
    -> m (Benchmark (BenchPhase (ExceptT e m)))
    -> ExceptT e m (Benchmark (BenchPhase (ExceptT e m)))
    forall a b. (a -> b) -> a -> b
    $ m (Benchmark (BenchPhase m))
    m (Benchmark (BenchPhase (ExceptT e m)))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark
      putBenchmark :: Benchmark (BenchPhase (ExceptT e m)) -> ExceptT e m ()
    putBenchmark    = m () -> ExceptT e m ()
    forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> ExceptT e m ())
    -> (Benchmark (BenchPhase m) -> m ())
    -> Benchmark (BenchPhase m)
    -> ExceptT e m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Benchmark (BenchPhase m) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    Benchmark (BenchPhase m) -> m ()
    putBenchmark
      modifyBenchmark :: (Benchmark (BenchPhase (ExceptT e m))
     -> Benchmark (BenchPhase (ExceptT e m)))
    -> ExceptT e m ()
    modifyBenchmark = m () -> ExceptT e m ()
    forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> ExceptT e m ())
    -> ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> ExceptT e m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark
      finally :: forall b c. ExceptT e m b -> ExceptT e m c -> ExceptT e m b
    finally ExceptT e m b
    m ExceptT e m c
    f = m (Either e b) -> ExceptT e m b
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (m (Either e b) -> ExceptT e m b)
    -> m (Either e b) -> ExceptT e m b
    forall a b. (a -> b) -> a -> b
    $ m (Either e b) -> m (Either e c) -> m (Either e b)
    forall b c. m b -> m c -> m b
    forall (m :: * -> *) b c. MonadBench m => m b -> m c -> m b
    finally (ExceptT e m b -> m (Either e b)
    forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
    runExceptT ExceptT e m b
    m) (ExceptT e m c -> m (Either e c)
    forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
    runExceptT ExceptT e m c
    f)

    instance MonadBench m => MonadBench (ListT m) where
      type BenchPhase (ListT m) = BenchPhase m

      getBenchmark :: ListT m (Benchmark (BenchPhase (ListT m)))
    getBenchmark    = m (Benchmark (BenchPhase m)) -> ListT m (Benchmark (BenchPhase m))
    forall (m :: * -> *) a. Monad m => m a -> ListT m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (Benchmark (BenchPhase m))
    forall (m :: * -> *). MonadBench m => m (Benchmark (BenchPhase m))
    getBenchmark
      putBenchmark :: Benchmark (BenchPhase (ListT m)) -> ListT m ()
    putBenchmark    = m () -> ListT m ()
    forall (m :: * -> *) a. Monad m => m a -> ListT m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> ListT m ())
    -> (Benchmark (BenchPhase m) -> m ())
    -> Benchmark (BenchPhase m)
    -> ListT m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Benchmark (BenchPhase m) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    Benchmark (BenchPhase m) -> m ()
    putBenchmark
      modifyBenchmark :: (Benchmark (BenchPhase (ListT m))
     -> Benchmark (BenchPhase (ListT m)))
    -> ListT m ()
    modifyBenchmark = m () -> ListT m ()
    forall (m :: * -> *) a. Monad m => m a -> ListT m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m () -> ListT m ())
    -> ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> ListT m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark
      finally :: forall b c. ListT m b -> ListT m c -> ListT m b
    finally ListT m b
    m ListT m c
    f = m (Maybe (b, ListT m b)) -> ListT m b
    forall (m :: * -> *) a. m (Maybe (a, ListT m a)) -> ListT m a
    ListT (m (Maybe (b, ListT m b)) -> ListT m b)
    -> m (Maybe (b, ListT m b)) -> ListT m b
    forall a b. (a -> b) -> a -> b
    $ m (Maybe (b, ListT m b))
    -> m (Maybe (c, ListT m c)) -> m (Maybe (b, ListT m b))
    forall b c. m b -> m c -> m b
    forall (m :: * -> *) b c. MonadBench m => m b -> m c -> m b
    finally (ListT m b -> m (Maybe (b, ListT m b))
    forall (m :: * -> *) a. ListT m a -> m (Maybe (a, ListT m a))
    runListT ListT m b
    m) (ListT m c -> m (Maybe (c, ListT m c))
    forall (m :: * -> *) a. ListT m a -> m (Maybe (a, ListT m a))
    runListT ListT m c
    f)

    -- | Turn benchmarking on/off.

    setBenchmarking :: MonadBench m => BenchmarkOn (BenchPhase m) -> m ()
    setBenchmarking :: forall (m :: * -> *).
    MonadBench m =>
    BenchmarkOn (BenchPhase m) -> m ()
    setBenchmarking BenchmarkOn (BenchPhase m)
    b = (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall a b. (a -> b) -> a -> b
    $ (BenchmarkOn (BenchPhase m) -> BenchmarkOn (BenchPhase m))
    -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    forall a.
    (BenchmarkOn a -> BenchmarkOn a) -> Benchmark a -> Benchmark a
    mapBenchmarkOn ((BenchmarkOn (BenchPhase m) -> BenchmarkOn (BenchPhase m))
     -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> (BenchmarkOn (BenchPhase m) -> BenchmarkOn (BenchPhase m))
    -> Benchmark (BenchPhase m)
    -> Benchmark (BenchPhase m)
    forall a b. (a -> b) -> a -> b
    $ BenchmarkOn (BenchPhase m)
    -> BenchmarkOn (BenchPhase m) -> BenchmarkOn (BenchPhase m)
    forall a b. a -> b -> a
    const BenchmarkOn (BenchPhase m)
    b

    -- | Bill current account with time up to now.
    --   Switch to new account.
    --   Return old account (if any).

    switchBenchmarking :: MonadBench m
      => Strict.Maybe (Account (BenchPhase m))      -- ^ Maybe new account.
      -> m (Strict.Maybe (Account (BenchPhase m)))  -- ^ Maybe old account.
    switchBenchmarking :: forall (m :: * -> *).
    MonadBench m =>
    Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    switchBenchmarking Maybe (Account (BenchPhase m))
    newAccount = do
      now <- IO CPUTime -> m CPUTime
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CPUTime -> m CPUTime) -> IO CPUTime -> m CPUTime
    forall a b. (a -> b) -> a -> b
    $ IO CPUTime
    forall (m :: * -> *). MonadIO m => m CPUTime
    getCPUTime
      -- Stop and bill current benchmarking.
      oldAccount <- getsBenchmark currentAccount
      Strict.whenJust oldAccount $ \ (Account (BenchPhase m)
    acc, CPUTime
    start) ->
        (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall a b. (a -> b) -> a -> b
    $ Account (BenchPhase m)
    -> CPUTime -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    forall a.
    Ord a =>
    Account a -> CPUTime -> Benchmark a -> Benchmark a
    addCPUTime Account (BenchPhase m)
    acc (CPUTime -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> CPUTime -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    forall a b. (a -> b) -> a -> b
    $ CPUTime
    now CPUTime -> CPUTime -> CPUTime
    forall a. Num a => a -> a -> a
    - CPUTime
    start
      -- Switch to new account.
      modifyBenchmark $ mapCurrentAccount $ const $ (, now) <$> newAccount
      return $ fst <$> oldAccount

    -- | Resets the account and the timing information.

    reset :: MonadBench m => m ()
    reset :: forall (m :: * -> *). MonadBench m => m ()
    reset = (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall (m :: * -> *).
    MonadBench m =>
    (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    modifyBenchmark ((Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ())
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)) -> m ()
    forall a b. (a -> b) -> a -> b
    $
      (CurrentAccount (BenchPhase m) -> CurrentAccount (BenchPhase m))
    -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    forall a.
    (CurrentAccount a -> CurrentAccount a)
    -> Benchmark a -> Benchmark a
    mapCurrentAccount (CurrentAccount (BenchPhase m)
    -> CurrentAccount (BenchPhase m) -> CurrentAccount (BenchPhase m)
    forall a b. a -> b -> a
    const CurrentAccount (BenchPhase m)
    forall a. Maybe a
    Strict.Nothing) (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> (Benchmark (BenchPhase m) -> Benchmark (BenchPhase m))
    -> Benchmark (BenchPhase m)
    -> Benchmark (BenchPhase m)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
      (Timings (BenchPhase m) -> Timings (BenchPhase m))
    -> Benchmark (BenchPhase m) -> Benchmark (BenchPhase m)
    forall a. (Timings a -> Timings a) -> Benchmark a -> Benchmark a
    mapTimings (Timings (BenchPhase m)
    -> Timings (BenchPhase m) -> Timings (BenchPhase m)
    forall a b. a -> b -> a
    const Timings (BenchPhase m)
    forall a. Null a => a
    Trie.empty)

    {-# INLINABLE billTo #-}
    -- | Bill a computation to a specific account.
    --   Works even if the computation is aborted by an exception.

    billTo :: MonadBench m => Account (BenchPhase m) -> m c -> m c
    billTo :: forall (m :: * -> *) c.
    MonadBench m =>
    Account (BenchPhase m) -> m c -> m c
    billTo Account (BenchPhase m)
    account m c
    m = m Bool -> m c -> m c -> m c
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifNotM (Account (BenchPhase m) -> BenchmarkOn (BenchPhase m) -> Bool
    forall a. Account a -> BenchmarkOn a -> Bool
    isBenchmarkOn Account (BenchPhase m)
    account (BenchmarkOn (BenchPhase m) -> Bool)
    -> m (BenchmarkOn (BenchPhase m)) -> m Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Benchmark (BenchPhase m) -> BenchmarkOn (BenchPhase m))
    -> m (BenchmarkOn (BenchPhase m))
    forall (m :: * -> *) c.
    MonadBench m =>
    (Benchmark (BenchPhase m) -> c) -> m c
    getsBenchmark Benchmark (BenchPhase m) -> BenchmarkOn (BenchPhase m)
    forall a. Benchmark a -> BenchmarkOn a
    benchmarkOn) m c
    m (m c -> m c) -> m c -> m c
    forall a b. (a -> b) -> a -> b
    $ do
      -- Switch to new account.
      old <- Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    forall (m :: * -> *).
    MonadBench m =>
    Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    switchBenchmarking (Maybe (Account (BenchPhase m))
     -> m (Maybe (Account (BenchPhase m))))
    -> Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    forall a b. (a -> b) -> a -> b
    $ Account (BenchPhase m) -> Maybe (Account (BenchPhase m))
    forall a. a -> Maybe a
    Strict.Just Account (BenchPhase m)
    account
      -- Compute and switch back to old account.
      (liftIO . E.evaluate =<< m) `finally` switchBenchmarking old

    -- | Bill a CPS function to an account. Can't handle exceptions.
    billToCPS :: MonadBench m => Account (BenchPhase m) -> ((b -> m c) -> m c) -> (b -> m c) -> m c
    billToCPS :: forall (m :: * -> *) b c.
    MonadBench m =>
    Account (BenchPhase m) -> ((b -> m c) -> m c) -> (b -> m c) -> m c
    billToCPS Account (BenchPhase m)
    account (b -> m c) -> m c
    f b -> m c
    k = m Bool -> m c -> m c -> m c
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifNotM (Account (BenchPhase m) -> BenchmarkOn (BenchPhase m) -> Bool
    forall a. Account a -> BenchmarkOn a -> Bool
    isBenchmarkOn Account (BenchPhase m)
    account (BenchmarkOn (BenchPhase m) -> Bool)
    -> m (BenchmarkOn (BenchPhase m)) -> m Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Benchmark (BenchPhase m) -> BenchmarkOn (BenchPhase m))
    -> m (BenchmarkOn (BenchPhase m))
    forall (m :: * -> *) c.
    MonadBench m =>
    (Benchmark (BenchPhase m) -> c) -> m c
    getsBenchmark Benchmark (BenchPhase m) -> BenchmarkOn (BenchPhase m)
    forall a. Benchmark a -> BenchmarkOn a
    benchmarkOn) ((b -> m c) -> m c
    f b -> m c
    k) (m c -> m c) -> m c -> m c
    forall a b. (a -> b) -> a -> b
    $ do
      -- Switch to new account.
      old <- Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    forall (m :: * -> *).
    MonadBench m =>
    Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    switchBenchmarking (Maybe (Account (BenchPhase m))
     -> m (Maybe (Account (BenchPhase m))))
    -> Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    forall a b. (a -> b) -> a -> b
    $ Account (BenchPhase m) -> Maybe (Account (BenchPhase m))
    forall a. a -> Maybe a
    Strict.Just Account (BenchPhase m)
    account
      f $ \ b
    x -> b
    x b -> m c -> m c
    forall a b. a -> b -> b
    `seq` do
        _ <- Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    forall (m :: * -> *).
    MonadBench m =>
    Maybe (Account (BenchPhase m))
    -> m (Maybe (Account (BenchPhase m)))
    switchBenchmarking Maybe (Account (BenchPhase m))
    old
        k x

    -- | Bill a pure computation to a specific account.
    billPureTo :: MonadBench m  => Account (BenchPhase m) -> c -> m c
    billPureTo :: forall (m :: * -> *) c.
    MonadBench m =>
    Account (BenchPhase m) -> c -> m c
    billPureTo Account (BenchPhase m)
    account = Account (BenchPhase m) -> m c -> m c
    forall (m :: * -> *) c.
    MonadBench m =>
    Account (BenchPhase m) -> m c -> m c
    billTo Account (BenchPhase m)
    account (m c -> m c) -> (c -> m c) -> c -> m c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . c -> m c
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return

    -- NFData instances.

    instance NFData a => NFData (BenchmarkOn a)
    instance NFData a => NFData (Benchmark a)