    {-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Control.Parallel.Strategies
    -- Copyright   :  (c) The University of Glasgow 2001-2010
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  libraries@haskell.org
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- Parallel Evaluation Strategies, or Strategies for short, provide
    -- ways to express parallel computations.  Strategies have the following
    -- key features:
    --
    --  * Strategies express /deterministic parallelism/:
    --    the result of the program is unaffected by evaluating in parallel.
    --    The parallel tasks evaluated by a Strategy may have no side effects.
    --    For non-deterministic parallel programming, see "Control.Concurrent".
    --
    --  * Strategies let you separate the description of the parallelism from the
    --    logic of your program, enabling modular parallelism.  The basic idea
    --    is to build a lazy data structure representing the computation, and
    --    then write a Strategy that describes how to traverse the data structure
    --    and evaluate components of it sequentially or in parallel.
    --
    --  * Strategies are /compositional/: larger strategies can be built
    --    by gluing together smaller ones.
    --
    --  * 'Monad' and 'Applicative' instances are provided, for quickly building
    --    strategies that involve traversing structures in a regular way.
    --
    -- For API history and changes in this release, see "Control.Parallel.Strategies#history".

    -----------------------------------------------------------------------------

    module Control.Parallel.Strategies (
             -- * The strategy type
             Strategy

             -- * Application of strategies
           , using             -- :: a -> Strategy a -> a
           , withStrategy      -- :: Strategy a -> a -> a
           , usingIO           -- :: a -> Strategy a -> IO a
           , withStrategyIO    -- :: Strategy a -> a -> IO a

             -- * Composition of strategies
           , dot               -- :: Strategy a -> Strategy a -> Strategy a

             -- * Basic strategies
           , r0                -- :: Strategy a
           , rseq
           , rdeepseq          -- :: NFData a => Strategy a
           , rpar              -- :: Strategy a
           , rparWith          -- :: Strategy a -> Strategy a

             -- * Injection of sequential strategies
           , evalSeq           -- :: Seq.Strategy a -> Strategy a
           , SeqStrategy

             -- * Strategies for traversable data types
           , evalTraversable   -- :: Traversable t => Strategy a -> Strategy (t a)
           , parTraversable

             -- * Strategies for lists
           , evalList          -- :: Strategy a -> Strategy [a]
           , parList
           , evalListN         -- :: Int -> Strategy a -> Strategy [a]
           , parListN
           , evalListNth       -- :: Int -> Strategy a -> Strategy [a]
           , parListNth
           , evalListSplitAt   -- :: Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
           , parListSplitAt
           , parListChunk
           , parMap

             -- ** Strategies for lazy lists
           , evalBuffer        -- :: Int -> Strategy a -> Strategy [a]
           , parBuffer

             -- * Strategies for tuples

             -- | Evaluate the components of a tuple according to the
             -- given strategies.

           , evalTuple2        -- :: Strategy a -> ... -> Strategy (a,...)
           , evalTuple3
           , evalTuple4
           , evalTuple5
           , evalTuple6
           , evalTuple7
           , evalTuple8
           , evalTuple9

           -- | Evaluate the components of a tuple in parallel according to
           -- the given strategies.

           , parTuple2         -- :: Strategy a -> ... -> Strategy (a,...)
           , parTuple3
           , parTuple4
           , parTuple5
           , parTuple6
           , parTuple7
           , parTuple8
           , parTuple9

             -- * Strategic function application
           , ($|)              -- :: (a -> b) -> Strategy a -> a -> b
           , ($||)
           , (.|)              -- :: (b -> c) -> Strategy b -> (a -> b) -> a -> c
           , (.||)
           , (-|)              -- :: (a -> b) -> Strategy b -> (b -> c) -> a -> c
           , (-||)

             -- * For Strategy programmers
           , Eval              -- instances: Monad, Functor, Applicative
           , parEval           -- :: Eval a -> Eval a
           , runEval           -- :: Eval a -> a
           , runEvalIO         -- :: Eval a -> IO a
           ,

        -- * API History

        -- $history

        -- * Backwards compatibility

        -- | These functions and types are all deprecated, and will be
        -- removed in a future release.  In all cases they have been
        -- either renamed or replaced with equivalent functionality.

        Done, demanding, sparking, (>|), (>||),
        rwhnf, unEval,
        seqTraverse, parTraverse,
        seqList,
        seqPair, parPair,
        seqTriple, parTriple,

        -- * For API completeness

        -- | so users of 'rdeepseq' aren't required to import Control.DeepSeq:
        NFData
      ) where

    #if !MIN_VERSION_base(4,8,0)
    import Data.Traversable
    import Control.Applicative
    #endif
    import Control.Parallel
    import Control.DeepSeq (NFData(rnf))
    import Control.Monad.Fix (MonadFix (..))

    #if MIN_VERSION_base(4,4,0)
    import System.IO.Unsafe (unsafeDupablePerformIO)
    import Control.Exception (evaluate)
    #else
    import System.IO.Unsafe (unsafePerformIO)
    import Control.Monad
    #endif

    import qualified Control.Seq

    import GHC.Exts
    import GHC.IO (IO (..))

    infixr 9 `dot`     -- same as (.)
    infixl 0 `using`   -- lowest precedence and associate to the left
    infixl 0 `usingIO` -- lowest precedence and associate to the left

    -- -----------------------------------------------------------------------------
    -- Eval monad (isomorphic to Lift monad from MonadLib 3.6.1)

    -- | 'Eval' is a Monad that makes it easier to define parallel
    -- strategies.  It is a strict identity monad: that is, in
    --
    --  > m >>= f
    --
    -- @m@ is evaluated before the result is passed to @f@.
    --
    --  > instance Monad Eval where
    --  >   return  = Done
    --  >   m >>= k = case m of
    --  >               Done x -> k x
    --
    -- If you wanted to construct a 'Strategy' for a pair that sparked the
    -- first component in parallel and then evaluated the second
    -- component, you could write
    --
    -- > myStrat :: Strategy (a,b)
    -- > myStrat (a,b) = do { a' <- rpar a; b' <- rseq b; return (a',b') }
    --
    -- Alternatively, you could write this more compactly using the
    -- Applicative style as
    --
    -- > myStrat (a,b) = (,) <$> rpar a <*> rseq b

    -- More examples, using the Applicative instance:
    --
    -- > parList :: Strategy a -> Strategy [a]
    -- > parList strat = traverse (rpar `dot` strat))
    --
    -- > evalPair :: Strategy a -> Strategy b -> Strategy (a,b)
    -- > evalPair f g (a,b) = pure (,) <$> f a <*> g b
    --

    #if __GLASGOW_HASKELL__ >= 702

    newtype Eval a = Eval {forall a. Eval a -> IO a
    unEval_ :: IO a}
      deriving ((forall a b. (a -> b) -> Eval a -> Eval b)
    -> (forall a b. a -> Eval b -> Eval a) -> Functor Eval
    forall a b. a -> Eval b -> Eval a
    forall a b. (a -> b) -> Eval a -> Eval 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) -> Eval a -> Eval b
    fmap :: forall a b. (a -> b) -> Eval a -> Eval b
    $c<$ :: forall a b. a -> Eval b -> Eval a
    <$ :: forall a b. a -> Eval b -> Eval a
    Functor, Functor Eval
    Functor Eval =>
    (forall a. a -> Eval a)
    -> (forall a b. Eval (a -> b) -> Eval a -> Eval b)
    -> (forall a b c. (a -> b -> c) -> Eval a -> Eval b -> Eval c)
    -> (forall a b. Eval a -> Eval b -> Eval b)
    -> (forall a b. Eval a -> Eval b -> Eval a)
    -> Applicative Eval
    forall a. a -> Eval a
    forall a b. Eval a -> Eval b -> Eval a
    forall a b. Eval a -> Eval b -> Eval b
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall a b c. (a -> b -> c) -> Eval a -> Eval b -> Eval 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 -> Eval a
    pure :: forall a. a -> Eval a
    $c<*> :: forall a b. Eval (a -> b) -> Eval a -> Eval b
    <*> :: forall a b. Eval (a -> b) -> Eval a -> Eval b
    $cliftA2 :: forall a b c. (a -> b -> c) -> Eval a -> Eval b -> Eval c
    liftA2 :: forall a b c. (a -> b -> c) -> Eval a -> Eval b -> Eval c
    $c*> :: forall a b. Eval a -> Eval b -> Eval b
    *> :: forall a b. Eval a -> Eval b -> Eval b
    $c<* :: forall a b. Eval a -> Eval b -> Eval a
    <* :: forall a b. Eval a -> Eval b -> Eval a
    Applicative, Applicative Eval
    Applicative Eval =>
    (forall a b. Eval a -> (a -> Eval b) -> Eval b)
    -> (forall a b. Eval a -> Eval b -> Eval b)
    -> (forall a. a -> Eval a)
    -> Monad Eval
    forall a. a -> Eval a
    forall a b. Eval a -> Eval b -> Eval b
    forall a b. Eval a -> (a -> Eval b) -> Eval 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. Eval a -> (a -> Eval b) -> Eval b
    >>= :: forall a b. Eval a -> (a -> Eval b) -> Eval b
    $c>> :: forall a b. Eval a -> Eval b -> Eval b
    >> :: forall a b. Eval a -> Eval b -> Eval b
    $creturn :: forall a. a -> Eval a
    return :: forall a. a -> Eval a
    Monad)
      -- GHC 7.2.1 added the seq# and spark# primitives, that we use in
      -- the Eval monad implementation in order to get the correct
      -- strictness behaviour.

    -- | Pull the result out of the monad.
    runEval :: Eval a -> a
    #  if MIN_VERSION_base(4,4,0)
    runEval :: forall a. Eval a -> a
    runEval = IO a -> a
    forall a. IO a -> a
    unsafeDupablePerformIO (IO a -> a) -> (Eval a -> IO a) -> Eval a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Eval a -> IO a
    forall a. Eval a -> IO a
    unEval_
    #  else
    runEval = unsafePerformIO . unEval_
    #  endif

    -- | Run the evaluation in the 'IO' monad. This allows sequencing of
    -- evaluations relative to 'IO' actions.
    runEvalIO :: Eval a -> IO a
    runEvalIO :: forall a. Eval a -> IO a
    runEvalIO = Eval a -> IO a
    forall a. Eval a -> IO a
    unEval_

    -- We don't use GND to derive MonadFix from the IO instance. The IO instance
    -- has to be very careful to ensure that lazy blackholing doesn't cause IO
    -- actions to be duplicated in case of an infinite loop. This has a small
    -- performance cost. Eval computations are always assumed to be pure, so
    -- duplicating them is okay. What about ST computations embedded in Eval ones?
    -- Those also shouldn't be a problem: the ST computations are "closed", so it's
    -- safe to duplicate them, and the RTS already takes care to avoid resuming
    -- a computation paused by an asynchronous exception in multiple threads.
    -- Lazy ST takes care of itself with noDuplicate#, so we don't really need
    -- to think about it too much.
    --
    -- Note:
    --   mfix f = let res = runEval (Lift <$> f (unLift res))
    --            in case res of Lift r -> return r
    -- data Lift a = Lift a
    instance MonadFix Eval where
      -- Borrowed from the instance for ST
      mfix :: forall a. (a -> Eval a) -> Eval a
    mfix a -> Eval a
    k = IO a -> Eval a
    forall a. IO a -> Eval a
    Eval (IO a -> Eval a) -> IO a -> Eval a
    forall a b. (a -> b) -> a -> b
    $ (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    IO ((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)
    -> (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \ State# RealWorld
    s ->
        let ans :: Evret a
    ans       = Eval a -> State# RealWorld -> Evret a
    forall a. Eval a -> State# RealWorld -> Evret a
    liftEv (a -> Eval a
    k a
    r) State# RealWorld
    s
            Evret State# RealWorld
    _ a
    r = Evret a
    ans
        in
        case Evret a
    ans of Evret State# RealWorld
    s' a
    x -> (# State# RealWorld
    s', a
    x #)

    data Evret a = Evret (State# RealWorld) a

    -- liftEv is useful when we want a lifted result from an Eval computation. It
    -- is used to implement mfix.
    liftEv :: Eval a -> State# RealWorld -> Evret a
    liftEv :: forall a. Eval a -> State# RealWorld -> Evret a
    liftEv (Eval (IO State# RealWorld -> (# State# RealWorld, a #)
    m)) = \State# RealWorld
    s -> case State# RealWorld -> (# State# RealWorld, a #)
    m State# RealWorld
    s of (# State# RealWorld
    s', a
    r #) -> State# RealWorld -> a -> Evret a
    forall a. State# RealWorld -> a -> Evret a
    Evret State# RealWorld
    s' a
    r

    #else

    data Eval a = Done a

    -- | Pull the result out of the monad.
    runEval :: Eval a -> a
    runEval (Done x) = x

    -- | Run the evaluation in the 'IO' monad. This allows sequencing of
    -- evaluations relative to 'IO' actions.
    runEvalIO :: Eval a -> IO a
    runEvalIO (Done x) = return x

    instance Functor Eval where
      fmap = liftM

    instance Applicative Eval where
      pure = Done
      (<*>) = ap

    instance Monad Eval where
      return = pure
      Done x >>= k = lazy (k x)   -- Note: pattern 'Done x' makes '>>=' strict

    instance MonadFix Eval where
      mfix f = let r = f (runEval r) in r

    {-# RULES "lazy Done" forall x . lazy (Done x) = Done x #-}

    -- The Eval monad satisfies the monad laws.
    --
    -- (1) Left identity:
    --     return x >>= f ==> Done x >>= f ==> f x
    --
    -- (2) Right identity:
    --     (i)  m >>= return =*> Done u >>= return
    --                       ==> return u
    --                       ==> Done u <*= m
    --     (ii) m >>= return =*> undefined >>= return
    --                       ==> undefined <*= m
    --
    -- (3) Associativity:
    --     (i)  (m >>= f) >>= g =*> (Done u >>= f) >>= g
    --                          ==> f u >>= g <== (\x -> f x >>= g) u
    --                                        <== Done u >>= (\x -> f x >>= g)
    --                                        <*= m >>= (\x -> f x >>= g)
    --     (ii) (m >>= f) >>= g =*> (undefined >>= f) >>= g
    --                          ==> undefined >>= g
    --                          ==> undefined <== undefined >>= (\x -> f x >>= g)
    --                                        <*= m >>= (\x -> f x >>= g)

    #endif

    -- -----------------------------------------------------------------------------
    -- Strategies

    -- | A 'Strategy' is a function that embodies a parallel evaluation strategy.
    -- The function traverses (parts of) its argument, evaluating subexpressions
    -- in parallel or in sequence.
    --
    -- A 'Strategy' may do an arbitrary amount of evaluation of its
    -- argument, but should not return a value different from the one it
    -- was passed.
    --
    -- Parallel computations may be discarded by the runtime system if the
    -- program no longer requires their result, which is why a 'Strategy'
    -- function returns a new value equivalent to the old value.  The
    -- intention is that the program applies the 'Strategy' to a
    -- structure, and then uses the returned value, discarding the old
    -- value.  This idiom is expressed by the 'using' function.
    --
    type Strategy a = a -> Eval a

    -- | Evaluate a value using the given 'Strategy'.
    --
    -- > x `using` s = runEval (s x)
    --
    using :: a -> Strategy a -> a
    a
    x using :: forall a. a -> Strategy a -> a
    `using` Strategy a
    strat = Eval a -> a
    forall a. Eval a -> a
    runEval (Strategy a
    strat a
    x)

    -- | evaluate a value using the given 'Strategy'.  This is simply
    -- 'using' with the arguments reversed.
    --
    withStrategy :: Strategy a -> a -> a
    withStrategy :: forall a. Strategy a -> a -> a
    withStrategy = (a -> Strategy a -> a) -> Strategy a -> a -> a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip a -> Strategy a -> a
    forall a. a -> Strategy a -> a
    using

    -- | Evaluate a value using the given 'Strategy' inside the 'IO' monad.  See
    -- also 'runEvalIO'.
    --
    -- > x `usingIO` s = runEvalIO (s x)
    --
    usingIO :: a -> Strategy a -> IO a
    a
    x usingIO :: forall a. a -> Strategy a -> IO a
    `usingIO` Strategy a
    strat = Eval a -> IO a
    forall a. Eval a -> IO a
    runEvalIO (Strategy a
    strat a
    x)

    -- | Evaluate a value using the given 'Strategy' inside the 'IO' monad.  This
    -- is simply 'usingIO' with the arguments reversed.
    --
    withStrategyIO :: Strategy a -> a -> IO a
    withStrategyIO :: forall a. Strategy a -> a -> IO a
    withStrategyIO = (a -> Strategy a -> IO a) -> Strategy a -> a -> IO a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip a -> Strategy a -> IO a
    forall a. a -> Strategy a -> IO a
    usingIO

    -- | Compose two strategies sequentially.
    -- This is the analogue to function composition on strategies.
    --
    -- For any strategies @strat1@, @strat2@, and @strat3@,
    --
    -- > (strat1 `dot` strat2) `dot` strat3 == strat1 `dot` (strat2 `dot` strat3)
    -- > strat1 `dot` strat1 = strat1
    -- > strat1 `dot` r0 == strat1
    --
    -- > strat2 `dot` strat1 == strat2 . withStrategy strat1
    --
    dot :: Strategy a -> Strategy a -> Strategy a
    Strategy a
    strat2 dot :: forall a. Strategy a -> Strategy a -> Strategy a
    `dot` Strategy a
    strat1 = Strategy a
    strat2 Strategy a -> (a -> a) -> Strategy a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Eval a -> a
    forall a. Eval a -> a
    runEval (Eval a -> a) -> Strategy a -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Strategy a
    strat1

    -- Proof of strat2 `dot` strat1 == strat2 . withStrategy strat1
    --
    --    strat2 . withStrategy strat1
    -- == \x -> strat2 (withStrategy strat1 x)
    -- == \x -> strat2 (x `using` strat1)
    -- == \x -> strat2 (runEval (strat1 x))
    -- == \x -> (strat2 . runEval . strat1) x
    -- == strat2 `dot` strat1

    -- One might be tempted to think that 'dot' is equivalent to '(<=<)',
    -- the right-to-left Kleisli composition in the Eval monad, because
    -- '(<=<)' can take the type @Strategy a -> Strategy a -> Strategy a@
    -- and intuitively does what 'dot' does: First apply the strategy to the
    -- right then the one to the left. However, there is a subtle difference
    -- in strictness, witnessed by the following example:
    --
    -- > (r0 `dot` rseq) undefined == Done undefined
    -- > (r0 <=< rseq) undefined == undefined
    --

    -- | Inject a sequential strategy (ie. coerce a sequential strategy
    -- to a general strategy).
    --
    -- Thanks to 'evalSeq', the type @Control.Seq.Strategy a@ is a subtype
    -- of @'Strategy' a@.
    evalSeq :: SeqStrategy a -> Strategy a
    evalSeq :: forall a. SeqStrategy a -> Strategy a
    evalSeq SeqStrategy a
    strat a
    x = SeqStrategy a
    strat a
    x () -> Eval a -> Eval a
    forall a b. a -> b -> b
    `pseq` a -> Eval a
    forall a. a -> Eval a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x

    -- | A name for @Control.Seq.Strategy@, for documentation only.
    type SeqStrategy a = Control.Seq.Strategy a

    -- --------------------------------------------------------------------------
    -- Basic strategies (some imported from SeqStrategies)

    -- | 'r0' performs *no* evaluation.
    --
    -- > r0 == evalSeq Control.Seq.r0
    --
    r0 :: Strategy a
    r0 :: forall a. a -> Eval a
    r0 a
    x = a -> Eval a
    forall a. a -> Eval a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x

    -- Proof of r0 == evalSeq Control.Seq.r0
    --
    --    evalSeq Control.Seq.r0
    -- == \x -> Control.Seq.r0 x `pseq` return x
    -- == \x -> Control.Seq.Done `pseq` return x
    -- == \x -> return x
    -- == r0

    -- | 'rseq' evaluates its argument to weak head normal form.
    --
    -- > rseq == evalSeq Control.Seq.rseq
    --
    rseq :: Strategy a
    #if __GLASGOW_HASKELL__ >= 702
    rseq :: forall a. a -> Eval a
    rseq a
    x = IO a -> Eval a
    forall a. IO a -> Eval a
    Eval (a -> IO a
    forall a. a -> IO a
    evaluate a
    x)
    #else
    rseq x = x `seq` return x
    #endif
    -- Staged NOINLINE so we can match on rseq in RULES
    {-# NOINLINE [1] rseq #-}

    -- Proof of rseq == evalSeq Control.Seq.rseq
    --
    --    evalSeq Control.Seq.rseq
    -- == \x -> Control.Seq.rseq x `pseq` return x
    -- == \x -> (x `seq` Control.Seq.Done) `pseq` return x
    -- == \x -> x `pseq` return x
    -- == rseq

    -- | 'rdeepseq' fully evaluates its argument.
    --
    -- > rdeepseq == evalSeq Control.Seq.rdeepseq
    --
    rdeepseq :: NFData a => Strategy a
    rdeepseq :: forall a. NFData a => Strategy a
    rdeepseq a
    x = do Strategy ()
    forall a. a -> Eval a
    rseq (a -> ()
    forall a. NFData a => a -> ()
    rnf a
    x); a -> Eval a
    forall a. a -> Eval a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x

    -- Proof of rdeepseq == evalSeq Control.Seq.rdeepseq
    --
    --    evalSeq Control.Seq.rdeepseq
    -- == \x -> Control.Seq.rdeepseq x `pseq` return x
    -- == \x -> (x `deepseq` Control.Seq.Done) `pseq` return x
    -- == \x -> (rnf x `seq` Control.Seq.Done) `pseq` return x
    -- == \x -> rnf x `pseq` return x
    -- == rdeepseq

    -- | 'rpar' sparks its argument (for evaluation in parallel).
    rpar :: Strategy a
    #if __GLASGOW_HASKELL__ >= 702
    rpar :: forall a. a -> Eval a
    rpar  a
    x = IO a -> Eval a
    forall a. IO a -> Eval a
    Eval (IO a -> Eval a) -> IO a -> Eval a
    forall a b. (a -> b) -> a -> b
    $ (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    IO ((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)
    -> (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \State# RealWorld
    s -> a -> State# RealWorld -> (# State# RealWorld, a #)
    forall a d. a -> State# d -> (# State# d, a #)
    spark# a
    x State# RealWorld
    s
    #else
    rpar  x = case (par# x) of { _ -> Done x }
    #endif
    {-# INLINE rpar  #-}

    -- | Perform a computation in parallel using a strategy.
    --
    -- @
    -- rparWith strat x
    -- @
    --
    -- will spark @strat x@. Note that @rparWith strat@ is /not/ the
    -- same as @rpar `dot` strat@. Specifically, @rpar `dot` strat@
    -- always sparks a computation to reduce the result of the
    -- strategic computation to WHNF, while @rparWith strat@ need
    -- not.
    --
    -- > rparWith r0 = r0
    -- > rparWith rpar = rpar
    -- > rparWith rseq = rpar
    --
    -- @rparWith rpar x@ creates a spark that immediately creates another
    -- spark to evaluate @x@. We consider this equivalent to @rpar@ because
    -- there isn't any real additional parallelism. However, it is always
    -- less efficient because there's a bit of extra work to create the
    -- first (useless) spark. Similarly, @rparWith r0@ creates a spark
    -- that does precisely nothing. No real parallelism is added, but there
    -- is a bit of extra work to do nothing.
    rparWith :: Strategy a -> Strategy a
    rparWith :: forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat = Eval a -> Eval a
    forall a. Eval a -> Eval a
    parEval (Eval a -> Eval a) -> Strategy a -> Strategy a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Strategy a
    strat

    -- | 'parEval' sparks the computation of its argument for evaluation in
    -- parallel. Unlike @'rpar' . 'runEval'@, 'parEval'
    --
    --  * does not exit the `Eval` monad
    --
    --  * does not have a built-in `rseq`, so for example @'parEval' ('r0' x)@
    --    behaves as you might expect (it creates a spark that does no
    --    evaluation).
    --
    -- It is related to 'rparWith' by the following equality:
    --
    -- > parEval . strat = rparWith strat
    --
    parEval :: Eval a -> Eval a
    -- The intermediate `Lift` box is necessary, in order to avoid a built-in
    -- `rseq` in `parEval`. In particular, we want @parEval . r0 = r0@, not
    -- @parEval . r0 = rpar@.
    parEval :: forall a. Eval a -> Eval a
    parEval Eval a
    m = do
      l <- Strategy (Lift a)
    forall a. a -> Eval a
    rpar Lift a
    r
      return (case l of Lift a
    x -> a
    x)

      where
        r :: Lift a
    r = Eval (Lift a) -> Lift a
    forall a. Eval a -> a
    runEval (a -> Lift a
    forall a. a -> Lift a
    Lift (a -> Lift a) -> Eval a -> Eval (Lift a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Eval a
    m)

    data Lift a = Lift a

    -- --------------------------------------------------------------------------
    -- Strategy combinators for Traversable data types

    -- | Evaluate the elements of a traversable data structure
    -- according to the given strategy.
    evalTraversable :: Traversable t => Strategy a -> Strategy (t a)
    evalTraversable :: forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    evalTraversable = (a -> Eval a) -> t a -> Eval (t a)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b)
    traverse
    {-# INLINE evalTraversable #-}

    -- | Like 'evalTraversable' but evaluates all elements in parallel.
    parTraversable :: Traversable t => Strategy a -> Strategy (t a)
    parTraversable :: forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    parTraversable Strategy a
    strat = Strategy a -> Strategy (t a)
    forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    evalTraversable (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat)
    {-# INLINE parTraversable #-}

    -- --------------------------------------------------------------------------
    -- Strategies for lists

    -- | Evaluate each element of a list according to the given strategy.
    --  Equivalent to 'evalTraversable' at the list type.
    evalList :: Strategy a -> Strategy [a]
    evalList :: forall a. Strategy a -> Strategy [a]
    evalList = Strategy a -> Strategy [a]
    forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    evalTraversable
    -- Alternative explicitly recursive definition:
    -- evalList strat []     = return []
    -- evalList strat (x:xs) = strat x >>= \x' ->
    --                         evalList strat xs >>= \xs' ->
    --                         return (x':xs')

    -- | Evaluate each element of a list in parallel according to given strategy.
    --  Equivalent to 'parTraversable' at the list type.
    parList :: Strategy a -> Strategy [a]
    parList :: forall a. Strategy a -> Strategy [a]
    parList = Strategy a -> Strategy [a]
    forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    parTraversable
    -- Alternative definition via evalList:
    -- parList strat = evalList (rparWith strat)

    -- | @'evaListSplitAt' n stratPref stratSuff@ evaluates the prefix
    -- (of length @n@) of a list according to @stratPref@ and its the suffix
    -- according to @stratSuff@.
    evalListSplitAt :: Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    evalListSplitAt :: forall a. Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    evalListSplitAt Int
    n Strategy [a]
    stratPref Strategy [a]
    stratSuff [a]
    xs
      = let ([a]
    ys,[a]
    zs) = Int -> [a] -> ([a], [a])
    forall a. Int -> [a] -> ([a], [a])
    splitAt Int
    n [a]
    xs in
        Strategy [a]
    stratPref [a]
    ys Eval [a] -> Strategy [a] -> Eval [a]
    forall a b. Eval a -> (a -> Eval b) -> Eval b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \[a]
    ys' ->
        Strategy [a]
    stratSuff [a]
    zs Eval [a] -> Strategy [a] -> Eval [a]
    forall a b. Eval a -> (a -> Eval b) -> Eval b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \[a]
    zs' ->
        Strategy [a]
    forall a. a -> Eval a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([a]
    ys' [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a]
    zs')

    -- | Like 'evalListSplitAt' but evaluates both sublists in parallel.
    parListSplitAt :: Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    parListSplitAt :: forall a. Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    parListSplitAt Int
    n Strategy [a]
    stratPref Strategy [a]
    stratSuff = Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    forall a. Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    evalListSplitAt Int
    n (Strategy [a] -> Strategy [a]
    forall a. Strategy a -> Strategy a
    rparWith Strategy [a]
    stratPref) (Strategy [a] -> Strategy [a]
    forall a. Strategy a -> Strategy a
    rparWith Strategy [a]
    stratSuff)

    -- | Evaluate the first n elements of a list according to the given strategy.
    evalListN :: Int -> Strategy a -> Strategy [a]
    evalListN :: forall a. Int -> Strategy a -> Strategy [a]
    evalListN Int
    n Strategy a
    strat = Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    forall a. Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    evalListSplitAt Int
    n (Strategy a -> Strategy [a]
    forall a. Strategy a -> Strategy [a]
    evalList Strategy a
    strat) Strategy [a]
    forall a. a -> Eval a
    r0

    -- | Like 'evalListN' but evaluates the first n elements in parallel.
    parListN :: Int -> Strategy a -> Strategy [a]
    parListN :: forall a. Int -> Strategy a -> Strategy [a]
    parListN Int
    n Strategy a
    strat = Int -> Strategy a -> Strategy [a]
    forall a. Int -> Strategy a -> Strategy [a]
    evalListN Int
    n (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat)

    -- | Evaluate the nth element of a list (if there is such) according to
    -- the given strategy.
    -- This nth is 0-based. For example, @[1, 2, 3, 4, 5] `using` evalListNth 4 rseq@
    -- will eval @5@, not @4@.
    -- The spine of the list up to the nth element is evaluated as a side effect.
    evalListNth :: Int -> Strategy a -> Strategy [a]
    evalListNth :: forall a. Int -> Strategy a -> Strategy [a]
    evalListNth Int
    n Strategy a
    strat = Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    forall a. Int -> Strategy [a] -> Strategy [a] -> Strategy [a]
    evalListSplitAt Int
    n Strategy [a]
    forall a. a -> Eval a
    r0 (Int -> Strategy a -> Strategy [a]
    forall a. Int -> Strategy a -> Strategy [a]
    evalListN Int
    1 Strategy a
    strat)

    -- | Like 'evalListN' but evaluates the nth element in parallel.
    parListNth :: Int -> Strategy a -> Strategy [a]
    parListNth :: forall a. Int -> Strategy a -> Strategy [a]
    parListNth Int
    n Strategy a
    strat = Int -> Strategy a -> Strategy [a]
    forall a. Int -> Strategy a -> Strategy [a]
    evalListNth Int
    n (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat)

    -- | Divides a list into chunks, and applies the strategy
    -- @'evalList' strat@ to each chunk in parallel.
    --
    -- It is expected that this function will be replaced by a more
    -- generic clustering infrastructure in the future.
    --
    -- If the chunk size is 1 or less, 'parListChunk' is equivalent to
    -- 'parList'
    --
    parListChunk :: Int -> Strategy a -> Strategy [a]
    parListChunk :: forall a. Int -> Strategy a -> Strategy [a]
    parListChunk Int
    n Strategy a
    strat [a]
    xs
      | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    1    = Strategy a -> Strategy [a]
    forall a. Strategy a -> Strategy [a]
    parList Strategy a
    strat [a]
    xs
      | Bool
    otherwise = [[a]] -> [a]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat ([[a]] -> [a]) -> Eval [[a]] -> Eval [a]
    forall a b. (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Strategy [a] -> Strategy [[a]]
    forall a. Strategy a -> Strategy [a]
    parList (Strategy a -> Strategy [a]
    forall a. Strategy a -> Strategy [a]
    evalList Strategy a
    strat) (Int -> [a] -> [[a]]
    forall a. Int -> [a] -> [[a]]
    chunk Int
    n [a]
    xs)

    chunk :: Int -> [a] -> [[a]]
    chunk :: forall a. Int -> [a] -> [[a]]
    chunk Int
    _ [] = []
    chunk Int
    n [a]
    xs = [a]
    as [a] -> [[a]] -> [[a]]
    forall a. a -> [a] -> [a]
    : Int -> [a] -> [[a]]
    forall a. Int -> [a] -> [[a]]
    chunk Int
    n [a]
    bs where ([a]
    as,[a]
    bs) = Int -> [a] -> ([a], [a])
    forall a. Int -> [a] -> ([a], [a])
    splitAt Int
    n [a]
    xs

    -- --------------------------------------------------------------------------
    -- Convenience

    -- | A combination of 'parList' and 'map', encapsulating a common pattern:
    --
    -- > parMap strat f = withStrategy (parList strat) . map f
    --
    parMap :: Strategy b -> (a -> b) -> [a] -> [b]
    parMap :: forall b a. Strategy b -> (a -> b) -> [a] -> [b]
    parMap Strategy b
    strat a -> b
    f = ([b] -> Strategy [b] -> [b]
    forall a. a -> Strategy a -> a
    `using` Strategy b -> Strategy [b]
    forall a. Strategy a -> Strategy [a]
    parList Strategy b
    strat) ([b] -> [b]) -> ([a] -> [b]) -> [a] -> [b]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> b) -> [a] -> [b]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> b
    f

    -- --------------------------------------------------------------------------
    -- Strategies for lazy lists

    -- List-based non-compositional rolling buffer strategy, evaluating list
    -- elements to weak head normal form.
    -- Not to be exported; used in evalBuffer and for optimisation.
    evalBufferWHNF :: Int -> Strategy [a]
    evalBufferWHNF :: forall a. Int -> Strategy [a]
    evalBufferWHNF Int
    n0 [a]
    xs0 = [a] -> Eval [a]
    forall a. a -> Eval a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([a] -> [a] -> [a]
    forall {a} {a}. [a] -> [a] -> [a]
    ret [a]
    xs0 (Int -> [a] -> [a]
    forall {t} {a}. (Eq t, Num t) => t -> [a] -> [a]
    start Int
    n0 [a]
    xs0))
      where -- ret :: [a] -> [a] -> [a]
               ret :: [a] -> [a] -> [a]
    ret (a
    x:[a]
    xs) (a
    y:[a]
    ys) = a
    y a -> [a] -> [a]
    forall a b. a -> b -> b
    `pseq` (a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a] -> [a] -> [a]
    ret [a]
    xs [a]
    ys)
               ret [a]
    xs     [a]
    _      = [a]
    xs

            -- start :: Int -> [a] -> [a]
               start :: t -> [a] -> [a]
    start t
    0   [a]
    ys     = [a]
    ys
               start !t
    _n []     = []
               start !t
    n  (a
    y:[a]
    ys) = a
    y a -> [a] -> [a]
    forall a b. a -> b -> b
    `pseq` t -> [a] -> [a]
    start (t
    nt -> t -> t
    forall a. Num a => a -> a -> a
    -t
    1) [a]
    ys

    -- | 'evalBuffer' is a rolling buffer strategy combinator for (lazy) lists.
    --
    -- 'evalBuffer' is not as compositional as the type suggests. In fact,
    -- it evaluates list elements at least to weak head normal form,
    -- disregarding a strategy argument 'r0'.
    --
    -- > evalBuffer n r0 == evalBuffer n rseq
    --
    evalBuffer :: Int -> Strategy a -> Strategy [a]
    evalBuffer :: forall a. Int -> Strategy a -> Strategy [a]
    evalBuffer Int
    n Strategy a
    strat =  Int -> Strategy [a]
    forall a. Int -> Strategy [a]
    evalBufferWHNF Int
    n Strategy [a] -> ([a] -> [a]) -> Strategy [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> a) -> [a] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map (Strategy a -> a -> a
    forall a. Strategy a -> a -> a
    withStrategy Strategy a
    strat)

    -- Like evalBufferWHNF but sparks the list elements when pushing them
    -- into the buffer.
    -- Not to be exported; used in parBuffer and for optimisation.
    parBufferWHNF :: Int -> Strategy [a]
    parBufferWHNF :: forall a. Int -> Strategy [a]
    parBufferWHNF Int
    n0 [a]
    xs0 = [a] -> Eval [a]
    forall a. a -> Eval a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([a] -> [a] -> [a]
    forall {a} {a}. [a] -> [a] -> [a]
    ret [a]
    xs0 (Int -> [a] -> [a]
    forall {t} {a}. (Eq t, Num t) => t -> [a] -> [a]
    start Int
    n0 [a]
    xs0))
      where -- ret :: [a] -> [a] -> [a]
               ret :: [a] -> [a] -> [a]
    ret (a
    x:[a]
    xs) (a
    y:[a]
    ys) = a
    y a -> [a] -> [a]
    forall a b. a -> b -> b
    `par` (a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a] -> [a] -> [a]
    ret [a]
    xs [a]
    ys)
               ret [a]
    xs     [a]
    _      = [a]
    xs

            -- start :: Int -> [a] -> [a]
               start :: t -> [a] -> [a]
    start t
    0   [a]
    ys     = [a]
    ys
               start !t
    _n []     = []
               start !t
    n  (a
    y:[a]
    ys) = a
    y a -> [a] -> [a]
    forall a b. a -> b -> b
    `par` t -> [a] -> [a]
    start (t
    nt -> t -> t
    forall a. Num a => a -> a -> a
    -t
    1) [a]
    ys

    -- | Like 'evalBuffer' but evaluates the list elements in parallel when
    -- pushing them into the buffer.
    parBuffer :: Int -> Strategy a -> Strategy [a]
    parBuffer :: forall a. Int -> Strategy a -> Strategy [a]
    parBuffer Int
    n Strategy a
    strat = Int -> Strategy [a]
    forall a. Int -> Strategy [a]
    parBufferWHNF Int
    n Strategy [a] -> ([a] -> [a]) -> Strategy [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> a) -> [a] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map (Strategy a -> a -> a
    forall a. Strategy a -> a -> a
    withStrategy Strategy a
    strat)
    -- Alternative definition via evalBuffer (may compromise firing of RULES):
    -- parBuffer n strat = evalBuffer n (rparWith strat)

    -- Deforest the intermediate list in parBuffer/evalBuffer when it is
    -- unnecessary:

    {-# NOINLINE [1] evalBuffer #-}
    {-# NOINLINE [1] parBuffer #-}
    {-# RULES
    "evalBuffer/rseq"  forall n . evalBuffer  n rseq = evalBufferWHNF n
    "parBuffer/rseq"   forall n . parBuffer   n rseq = parBufferWHNF  n
     #-}

    -- --------------------------------------------------------------------------
    -- Strategies for tuples

    evalTuple2 :: Strategy a -> Strategy b -> Strategy (a,b)
    evalTuple2 :: forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    evalTuple2 Strategy a
    strat1 Strategy b
    strat2 (a
    x1,b
    x2) =
      (a -> b -> (a, b)) -> Eval (a -> b -> (a, b))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,) Eval (a -> b -> (a, b)) -> Eval a -> Eval (b -> (a, b))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> (a, b)) -> Eval b -> Eval (a, b)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2

    evalTuple3 :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
    evalTuple3 :: forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    evalTuple3 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 (a
    x1,b
    x2,c
    x3) =
      (a -> b -> c -> (a, b, c)) -> Eval (a -> b -> c -> (a, b, c))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,) Eval (a -> b -> c -> (a, b, c))
    -> Eval a -> Eval (b -> c -> (a, b, c))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> c -> (a, b, c)) -> Eval b -> Eval (c -> (a, b, c))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval (c -> (a, b, c)) -> Eval c -> Eval (a, b, c)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3

    evalTuple4 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy (a,b,c,d)
    evalTuple4 :: forall a b c d.
    Strategy a
    -> Strategy b -> Strategy c -> Strategy d -> Strategy (a, b, c, d)
    evalTuple4 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 (a
    x1,b
    x2,c
    x3,d
    x4) =
      (a -> b -> c -> d -> (a, b, c, d))
    -> Eval (a -> b -> c -> d -> (a, b, c, d))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,,) Eval (a -> b -> c -> d -> (a, b, c, d))
    -> Eval a -> Eval (b -> c -> d -> (a, b, c, d))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> c -> d -> (a, b, c, d))
    -> Eval b -> Eval (c -> d -> (a, b, c, d))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval (c -> d -> (a, b, c, d)) -> Eval c -> Eval (d -> (a, b, c, d))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3 Eval (d -> (a, b, c, d)) -> Eval d -> Eval (a, b, c, d)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy d
    strat4 d
    x4

    evalTuple5 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy (a,b,c,d,e)
    evalTuple5 :: forall a b c d e.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy (a, b, c, d, e)
    evalTuple5 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 (a
    x1,b
    x2,c
    x3,d
    x4,e
    x5) =
      (a -> b -> c -> d -> e -> (a, b, c, d, e))
    -> Eval (a -> b -> c -> d -> e -> (a, b, c, d, e))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,,,) Eval (a -> b -> c -> d -> e -> (a, b, c, d, e))
    -> Eval a -> Eval (b -> c -> d -> e -> (a, b, c, d, e))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> c -> d -> e -> (a, b, c, d, e))
    -> Eval b -> Eval (c -> d -> e -> (a, b, c, d, e))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval (c -> d -> e -> (a, b, c, d, e))
    -> Eval c -> Eval (d -> e -> (a, b, c, d, e))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3 Eval (d -> e -> (a, b, c, d, e))
    -> Eval d -> Eval (e -> (a, b, c, d, e))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy d
    strat4 d
    x4 Eval (e -> (a, b, c, d, e)) -> Eval e -> Eval (a, b, c, d, e)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy e
    strat5 e
    x5

    evalTuple6 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy (a,b,c,d,e,f)
    evalTuple6 :: forall a b c d e f.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy (a, b, c, d, e, f)
    evalTuple6 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 (a
    x1,b
    x2,c
    x3,d
    x4,e
    x5,f
    x6) =
      (a -> b -> c -> d -> e -> f -> (a, b, c, d, e, f))
    -> Eval (a -> b -> c -> d -> e -> f -> (a, b, c, d, e, f))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,,,,) Eval (a -> b -> c -> d -> e -> f -> (a, b, c, d, e, f))
    -> Eval a -> Eval (b -> c -> d -> e -> f -> (a, b, c, d, e, f))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> c -> d -> e -> f -> (a, b, c, d, e, f))
    -> Eval b -> Eval (c -> d -> e -> f -> (a, b, c, d, e, f))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval (c -> d -> e -> f -> (a, b, c, d, e, f))
    -> Eval c -> Eval (d -> e -> f -> (a, b, c, d, e, f))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3 Eval (d -> e -> f -> (a, b, c, d, e, f))
    -> Eval d -> Eval (e -> f -> (a, b, c, d, e, f))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy d
    strat4 d
    x4 Eval (e -> f -> (a, b, c, d, e, f))
    -> Eval e -> Eval (f -> (a, b, c, d, e, f))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy e
    strat5 e
    x5 Eval (f -> (a, b, c, d, e, f)) -> Eval f -> Eval (a, b, c, d, e, f)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy f
    strat6 f
    x6

    evalTuple7 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy (a,b,c,d,e,f,g)
    evalTuple7 :: forall a b c d e f g.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy (a, b, c, d, e, f, g)
    evalTuple7 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 Strategy g
    strat7 (a
    x1,b
    x2,c
    x3,d
    x4,e
    x5,f
    x6,g
    x7) =
      (a -> b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    -> Eval (a -> b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,,,,,) Eval (a -> b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    -> Eval a
    -> Eval (b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    -> Eval b -> Eval (c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval (c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
    -> Eval c -> Eval (d -> e -> f -> g -> (a, b, c, d, e, f, g))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3 Eval (d -> e -> f -> g -> (a, b, c, d, e, f, g))
    -> Eval d -> Eval (e -> f -> g -> (a, b, c, d, e, f, g))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy d
    strat4 d
    x4 Eval (e -> f -> g -> (a, b, c, d, e, f, g))
    -> Eval e -> Eval (f -> g -> (a, b, c, d, e, f, g))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy e
    strat5 e
    x5 Eval (f -> g -> (a, b, c, d, e, f, g))
    -> Eval f -> Eval (g -> (a, b, c, d, e, f, g))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy f
    strat6 f
    x6 Eval (g -> (a, b, c, d, e, f, g))
    -> Eval g -> Eval (a, b, c, d, e, f, g)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy g
    strat7 g
    x7

    evalTuple8 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy (a,b,c,d,e,f,g,h)
    evalTuple8 :: forall a b c d e f g h.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy (a, b, c, d, e, f, g, h)
    evalTuple8 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 Strategy g
    strat7 Strategy h
    strat8 (a
    x1,b
    x2,c
    x3,d
    x4,e
    x5,f
    x6,g
    x7,h
    x8) =
      (a -> b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval
         (a -> b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,,,,,,) Eval
      (a -> b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval a
    -> Eval
         (b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval (b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval b
    -> Eval (c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval (c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval c
    -> Eval (d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3 Eval (d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval d -> Eval (e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy d
    strat4 d
    x4 Eval (e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval e -> Eval (f -> g -> h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy e
    strat5 e
    x5 Eval (f -> g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval f -> Eval (g -> h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy f
    strat6 f
    x6 Eval (g -> h -> (a, b, c, d, e, f, g, h))
    -> Eval g -> Eval (h -> (a, b, c, d, e, f, g, h))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy g
    strat7 g
    x7 Eval (h -> (a, b, c, d, e, f, g, h))
    -> Eval h -> Eval (a, b, c, d, e, f, g, h)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy h
    strat8 h
    x8

    evalTuple9 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy i -> Strategy (a,b,c,d,e,f,g,h,i)
    evalTuple9 :: forall a b c d e f g h i.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy i
    -> Strategy (a, b, c, d, e, f, g, h, i)
    evalTuple9 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 Strategy g
    strat7 Strategy h
    strat8 Strategy i
    strat9 (a
    x1,b
    x2,c
    x3,d
    x4,e
    x5,f
    x6,g
    x7,h
    x8,i
    x9) =
      (a
     -> b
     -> c
     -> d
     -> e
     -> f
     -> g
     -> h
     -> i
     -> (a, b, c, d, e, f, g, h, i))
    -> Eval
         (a
          -> b
          -> c
          -> d
          -> e
          -> f
          -> g
          -> h
          -> i
          -> (a, b, c, d, e, f, g, h, i))
    forall a. a -> Eval a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (,,,,,,,,) Eval
      (a
       -> b
       -> c
       -> d
       -> e
       -> f
       -> g
       -> h
       -> i
       -> (a, b, c, d, e, f, g, h, i))
    -> Eval a
    -> Eval
         (b
          -> c -> d -> e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy a
    strat1 a
    x1 Eval
      (b
       -> c -> d -> e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval b
    -> Eval
         (c -> d -> e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy b
    strat2 b
    x2 Eval
      (c -> d -> e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval c
    -> Eval (d -> e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy c
    strat3 c
    x3 Eval (d -> e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval d
    -> Eval (e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy d
    strat4 d
    x4 Eval (e -> f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval e -> Eval (f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy e
    strat5 e
    x5 Eval (f -> g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval f -> Eval (g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy f
    strat6 f
    x6 Eval (g -> h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval g -> Eval (h -> i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy g
    strat7 g
    x7 Eval (h -> i -> (a, b, c, d, e, f, g, h, i))
    -> Eval h -> Eval (i -> (a, b, c, d, e, f, g, h, i))
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy h
    strat8 h
    x8 Eval (i -> (a, b, c, d, e, f, g, h, i))
    -> Eval i -> Eval (a, b, c, d, e, f, g, h, i)
    forall a b. Eval (a -> b) -> Eval a -> Eval b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Strategy i
    strat9 i
    x9

    parTuple2 :: Strategy a -> Strategy b -> Strategy (a,b)
    parTuple2 :: forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    parTuple2 Strategy a
    strat1 Strategy b
    strat2 =
      Strategy a -> Strategy b -> Strategy (a, b)
    forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    evalTuple2 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2)

    parTuple3 :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
    parTuple3 :: forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    parTuple3 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 =
      Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    evalTuple3 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3)

    parTuple4 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy (a,b,c,d)
    parTuple4 :: forall a b c d.
    Strategy a
    -> Strategy b -> Strategy c -> Strategy d -> Strategy (a, b, c, d)
    parTuple4 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 =
      Strategy a
    -> Strategy b -> Strategy c -> Strategy d -> Strategy (a, b, c, d)
    forall a b c d.
    Strategy a
    -> Strategy b -> Strategy c -> Strategy d -> Strategy (a, b, c, d)
    evalTuple4 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3) (Strategy d -> Strategy d
    forall a. Strategy a -> Strategy a
    rparWith Strategy d
    strat4)

    parTuple5 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy (a,b,c,d,e)
    parTuple5 :: forall a b c d e.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy (a, b, c, d, e)
    parTuple5 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 =
      Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy (a, b, c, d, e)
    forall a b c d e.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy (a, b, c, d, e)
    evalTuple5 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3) (Strategy d -> Strategy d
    forall a. Strategy a -> Strategy a
    rparWith Strategy d
    strat4) (Strategy e -> Strategy e
    forall a. Strategy a -> Strategy a
    rparWith Strategy e
    strat5)

    parTuple6 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy (a,b,c,d,e,f)
    parTuple6 :: forall a b c d e f.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy (a, b, c, d, e, f)
    parTuple6 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 =
      Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy (a, b, c, d, e, f)
    forall a b c d e f.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy (a, b, c, d, e, f)
    evalTuple6 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3) (Strategy d -> Strategy d
    forall a. Strategy a -> Strategy a
    rparWith Strategy d
    strat4) (Strategy e -> Strategy e
    forall a. Strategy a -> Strategy a
    rparWith Strategy e
    strat5) (Strategy f -> Strategy f
    forall a. Strategy a -> Strategy a
    rparWith Strategy f
    strat6)

    parTuple7 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy (a,b,c,d,e,f,g)
    parTuple7 :: forall a b c d e f g.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy (a, b, c, d, e, f, g)
    parTuple7 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 Strategy g
    strat7 =
      Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy (a, b, c, d, e, f, g)
    forall a b c d e f g.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy (a, b, c, d, e, f, g)
    evalTuple7 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3) (Strategy d -> Strategy d
    forall a. Strategy a -> Strategy a
    rparWith Strategy d
    strat4) (Strategy e -> Strategy e
    forall a. Strategy a -> Strategy a
    rparWith Strategy e
    strat5) (Strategy f -> Strategy f
    forall a. Strategy a -> Strategy a
    rparWith Strategy f
    strat6) (Strategy g -> Strategy g
    forall a. Strategy a -> Strategy a
    rparWith Strategy g
    strat7)

    parTuple8 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy (a,b,c,d,e,f,g,h)
    parTuple8 :: forall a b c d e f g h.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy (a, b, c, d, e, f, g, h)
    parTuple8 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 Strategy g
    strat7 Strategy h
    strat8 =
      Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy (a, b, c, d, e, f, g, h)
    forall a b c d e f g h.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy (a, b, c, d, e, f, g, h)
    evalTuple8 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3) (Strategy d -> Strategy d
    forall a. Strategy a -> Strategy a
    rparWith Strategy d
    strat4) (Strategy e -> Strategy e
    forall a. Strategy a -> Strategy a
    rparWith Strategy e
    strat5) (Strategy f -> Strategy f
    forall a. Strategy a -> Strategy a
    rparWith Strategy f
    strat6) (Strategy g -> Strategy g
    forall a. Strategy a -> Strategy a
    rparWith Strategy g
    strat7) (Strategy h -> Strategy h
    forall a. Strategy a -> Strategy a
    rparWith Strategy h
    strat8)

    parTuple9 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy i -> Strategy (a,b,c,d,e,f,g,h,i)
    parTuple9 :: forall a b c d e f g h i.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy i
    -> Strategy (a, b, c, d, e, f, g, h, i)
    parTuple9 Strategy a
    strat1 Strategy b
    strat2 Strategy c
    strat3 Strategy d
    strat4 Strategy e
    strat5 Strategy f
    strat6 Strategy g
    strat7 Strategy h
    strat8 Strategy i
    strat9 =
      Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy i
    -> Strategy (a, b, c, d, e, f, g, h, i)
    forall a b c d e f g h i.
    Strategy a
    -> Strategy b
    -> Strategy c
    -> Strategy d
    -> Strategy e
    -> Strategy f
    -> Strategy g
    -> Strategy h
    -> Strategy i
    -> Strategy (a, b, c, d, e, f, g, h, i)
    evalTuple9 (Strategy a -> Strategy a
    forall a. Strategy a -> Strategy a
    rparWith Strategy a
    strat1) (Strategy b -> Strategy b
    forall a. Strategy a -> Strategy a
    rparWith Strategy b
    strat2) (Strategy c -> Strategy c
    forall a. Strategy a -> Strategy a
    rparWith Strategy c
    strat3) (Strategy d -> Strategy d
    forall a. Strategy a -> Strategy a
    rparWith Strategy d
    strat4) (Strategy e -> Strategy e
    forall a. Strategy a -> Strategy a
    rparWith Strategy e
    strat5) (Strategy f -> Strategy f
    forall a. Strategy a -> Strategy a
    rparWith Strategy f
    strat6) (Strategy g -> Strategy g
    forall a. Strategy a -> Strategy a
    rparWith Strategy g
    strat7) (Strategy h -> Strategy h
    forall a. Strategy a -> Strategy a
    rparWith Strategy h
    strat8) (Strategy i -> Strategy i
    forall a. Strategy a -> Strategy a
    rparWith Strategy i
    strat9)

    -- --------------------------------------------------------------------------
    -- Strategic function application

    {-
    These are very handy when writing pipeline parallelism asa sequence of
    @$@, @$|@ and @$||@'s. There is no need of naming intermediate values
    in this case. The separation of algorithm from strategy is achieved by
    allowing strategies only as second arguments to @$|@ and @$||@.
    -}

    -- | Sequential function application. The argument is evaluated using
    --   the given strategy before it is given to the function.
    ($|) :: (a -> b) -> Strategy a -> a -> b
    a -> b
    f $| :: forall a b. (a -> b) -> Strategy a -> a -> b
    $| Strategy a
    s  = \ a
    x -> let z :: a
    z = a
    x a -> Strategy a -> a
    forall a. a -> Strategy a -> a
    `using` Strategy a
    s in a
    z a -> b -> b
    forall a b. a -> b -> b
    `pseq` a -> b
    f a
    z

    -- | Parallel function application. The argument is evaluated using
    -- the given strategy, in parallel with the function application.
    ($||) :: (a -> b) -> Strategy a -> a -> b
    a -> b
    f $|| :: forall a b. (a -> b) -> Strategy a -> a -> b
    $|| Strategy a
    s = \ a
    x -> let z :: a
    z = a
    x a -> Strategy a -> a
    forall a. a -> Strategy a -> a
    `using` Strategy a
    s in a
    z a -> b -> b
    forall a b. a -> b -> b
    `par` a -> b
    f a
    z

    -- | Sequential function composition. The result of
    -- the second function is evaluated using the given strategy,
    -- and then given to the first function.
    (.|) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
    .| :: forall b c a. (b -> c) -> Strategy b -> (a -> b) -> a -> c
    (.|) b -> c
    f Strategy b
    s a -> b
    g = \ a
    x -> let z :: b
    z = a -> b
    g a
    x b -> Strategy b -> b
    forall a. a -> Strategy a -> a
    `using` Strategy b
    s in
                        b
    z b -> c -> c
    forall a b. a -> b -> b
    `pseq` b -> c
    f b
    z

    -- | Parallel function composition. The result of the second
    -- function is evaluated using the given strategy,
    -- in parallel with the application of the first function.
    (.||) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
    .|| :: forall b c a. (b -> c) -> Strategy b -> (a -> b) -> a -> c
    (.||) b -> c
    f Strategy b
    s a -> b
    g = \ a
    x -> let z :: b
    z = a -> b
    g a
    x b -> Strategy b -> b
    forall a. a -> Strategy a -> a
    `using` Strategy b
    s in
                        b
    z b -> c -> c
    forall a b. a -> b -> b
    `par` b -> c
    f b
    z

    -- | Sequential inverse function composition,
    -- for those who read their programs from left to right.
    -- The result of the first function is evaluated using the
    -- given strategy, and then given to the second function.
    (-|) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
    -| :: forall a b c. (a -> b) -> Strategy b -> (b -> c) -> a -> c
    (-|) a -> b
    f Strategy b
    s b -> c
    g = \ a
    x -> let z :: b
    z = a -> b
    f a
    x b -> Strategy b -> b
    forall a. a -> Strategy a -> a
    `using` Strategy b
    s in
                        b
    z b -> c -> c
    forall a b. a -> b -> b
    `pseq` b -> c
    g b
    z

    -- | Parallel inverse function composition,
    -- for those who read their programs from left to right.
    -- The result of the first function is evaluated using the
    -- given strategy, in parallel with the application of the
    -- second function.
    (-||) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
    -|| :: forall a b c. (a -> b) -> Strategy b -> (b -> c) -> a -> c
    (-||) a -> b
    f Strategy b
    s b -> c
    g = \ a
    x -> let z :: b
    z = a -> b
    f a
    x b -> Strategy b -> b
    forall a. a -> Strategy a -> a
    `using` Strategy b
    s in
                        b
    z b -> c -> c
    forall a b. a -> b -> b
    `par` b -> c
    g b
    z

    -- -----------------------------------------------------------------------------
    -- Old/deprecated stuff

    {-# DEPRECATED Done "The Strategy type is now a -> Eval a, not a -> Done" #-}
    -- | DEPRECCATED: replaced by the 'Eval' monad
    type Done = ()

    {-# DEPRECATED demanding "Use pseq or $| instead" #-}
    -- | DEPRECATED: Use 'pseq' or '$|' instead
    demanding :: a -> Done -> a
    demanding :: forall a. a -> () -> a
    demanding = (() -> a -> a) -> a -> () -> a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip () -> a -> a
    forall a b. a -> b -> b
    pseq

    {-# DEPRECATED sparking "Use par or $|| instead" #-}
    -- | DEPRECATED: Use 'par' or '$||' instead
    sparking :: a -> Done -> a
    sparking :: forall a. a -> () -> a
    sparking  = (() -> a -> a) -> a -> () -> a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip () -> a -> a
    forall a b. a -> b -> b
    par

    {-# DEPRECATED (>|) "Use pseq or $| instead" #-}
    -- | DEPRECATED: Use 'pseq' or '$|' instead
    (>|) :: Done -> Done -> Done
    >| :: () -> () -> ()
    (>|) = () -> () -> ()
    forall a b. a -> b -> b
    Prelude.seq

    {-# DEPRECATED (>||) "Use par or $|| instead" #-}
    -- | DEPRECATED: Use 'par' or '$||' instead
    (>||) :: Done -> Done -> Done
    >|| :: () -> () -> ()
    (>||) = () -> () -> ()
    forall a b. a -> b -> b
    par

    {-# DEPRECATED rwhnf "renamed to rseq" #-}
    -- | DEPRECATED: renamed to 'rseq'
    rwhnf :: Strategy a
    rwhnf :: forall a. a -> Eval a
    rwhnf = Strategy a
    forall a. a -> Eval a
    rseq

    {-# DEPRECATED seqTraverse "renamed to evalTraversable" #-}
    -- | DEPRECATED: renamed to 'evalTraversable'
    seqTraverse :: Traversable t => Strategy a -> Strategy (t a)
    seqTraverse :: forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    seqTraverse = Strategy a -> Strategy (t a)
    forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    evalTraversable

    {-# DEPRECATED parTraverse "renamed to parTraversable" #-}
    -- | DEPRECATED: renamed to 'parTraversable'
    parTraverse :: Traversable t => Strategy a -> Strategy (t a)
    parTraverse :: forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    parTraverse = Strategy a -> Strategy (t a)
    forall (t :: * -> *) a.
    Traversable t =>
    Strategy a -> Strategy (t a)
    parTraversable

    {-# DEPRECATED seqList "renamed to evalList" #-}
    -- | DEPRECATED: renamed to 'evalList'
    seqList :: Strategy a -> Strategy [a]
    seqList :: forall a. Strategy a -> Strategy [a]
    seqList = Strategy a -> Strategy [a]
    forall a. Strategy a -> Strategy [a]
    evalList

    {-# DEPRECATED seqPair "renamed to evalTuple2" #-}
    -- | DEPRECATED: renamed to 'evalTuple2'
    seqPair :: Strategy a -> Strategy b -> Strategy (a,b)
    seqPair :: forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    seqPair = Strategy a -> Strategy b -> Strategy (a, b)
    forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    evalTuple2

    {-# DEPRECATED parPair "renamed to parTuple2" #-}
    -- | DEPRECATED: renamed to 'parTuple2'
    parPair :: Strategy a -> Strategy b -> Strategy (a,b)
    parPair :: forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    parPair = Strategy a -> Strategy b -> Strategy (a, b)
    forall a b. Strategy a -> Strategy b -> Strategy (a, b)
    parTuple2

    {-# DEPRECATED seqTriple "renamed to evalTuple3" #-}
    -- | DEPRECATED: renamed to 'evalTuple3'
    seqTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
    seqTriple :: forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    seqTriple = Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    evalTuple3

    {-# DEPRECATED parTriple "renamed to parTuple3" #-}
    -- | DEPRECATED: renamed to 'parTuple3'
    parTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
    parTriple :: forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    parTriple = Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    forall a b c.
    Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
    parTuple3

    {-# DEPRECATED unEval "renamed to runEval" #-}
    -- | DEPRECATED: renamed to 'runEval'
    unEval :: Eval a -> a
    unEval :: forall a. Eval a -> a
    unEval = Eval a -> a
    forall a. Eval a -> a
    runEval

    {- $history #history#

    The strategies library has a long history.  What follows is a
    summary of how the current design evolved, and is mostly of
    interest to those who are familiar with an older version, or need
    to adapt old code to use the newer API.

    Version 1.x

      The original Strategies design is described in /Algorithm + Strategy = Parallelism/ <http://www.macs.hw.ac.uk/~dsg/gph/papers/html/Strategies/strategies.html>
      and the code was written by
         Phil Trinder, Hans-Wolfgang Loidl, Kevin Hammond et al.

    Version 2.x

    Later, during work on the shared-memory implementation of
    parallelism in GHC, we discovered that the original formulation of
    Strategies had some problems, in particular it lead to space leaks
    and difficulties expressing speculative parallelism.  Details are in
    the paper /Runtime Support for Multicore Haskell/ <http://community.haskell.org/~simonmar/papers/multicore-ghc.pdf>.

    This module has been rewritten in version 2. The main change is to
    the 'Strategy a' type synonym, which was previously @a -> Done@ and
    is now @a -> Eval a@.  This change helps to fix the space leak described
    in \"Runtime Support for Multicore Haskell\".  The problem is that
    the runtime will currently retain the memory referenced by all
    sparks, until they are evaluated.  Hence, we must arrange to
    evaluate all the sparks eventually, just in case they aren't
    evaluated in parallel, so that they don't cause a space leak.  This
    is why we must return a \"new\" value after applying a 'Strategy',
    so that the application can evaluate each spark created by the
    'Strategy'.

    The simple rule is this: you /must/ use the result of applying
    a 'Strategy' if the strategy creates parallel sparks, and you
    should probably discard the the original value.  If you don't
    do this, currently it may result in a space leak.  In the
    future (GHC 6.14), it will probably result in lost parallelism
    instead, as we plan to change GHC so that unreferenced sparks
    are discarded rather than retained (we can't make this change
    until most code is switched over to this new version of
    Strategies, because code using the old verison of Strategies
    would be broken by the change in policy).

    The other changes in version 2.x are:

      * Strategies can now be defined using a convenient Monad/Applicative
        type, 'Eval'.  e.g. @parList s = traverse (Par . (``using`` s))@

      * 'parList' has been generalised to 'parTraverse', which works on
        any 'Traversable' type, and similarly 'seqList' has been generalised
        to 'seqTraverse'

      * 'parList' and 'parBuffer' have versions specialised to 'rwhnf',
        and there are transformation rules that automatically translate
        e.g. @parList rwnhf@ into a call to the optimised version.

      * 'NFData' has been moved to @Control.DeepSeq@ in the @deepseq@
        package.  Note that since the 'Strategy' type changed, 'rnf'
        is no longer a 'Strategy': use 'rdeepseq' instead.

    Version 2.1 moved NFData into a separate package, @deepseq@.

    Version 2.2 changed the type of Strategy to @a -> Eval a@, and
    re-introduced the @r0@ strategy which was missing in version 2.1.

    Version 2.3 simplified the @Eval@ type, so that @Eval@ is now just
    the strict identity monad.  This change and various other
    improvements and refactorings are thanks to Patrick Maier who
    noticed that @Eval@ didn't satisfy the monad laws, and that a
    simpler version would fix that problem.

    (version 2.3 was not released on Hackage).

    Version 3 introduced a major overhaul of the API, to match what is
    presented in the paper

      /Seq no More: Better Strategies for Parallel Haskell/
      <http://community.haskell.org/~simonmar/papers/strategies.pdf>

    The major differences in the API are:

     * The addition of Sequential strategies ("Control.Seq") as
       a composable means for specifying sequential evaluation.

     * Changes to the naming scheme: 'rwhnf' renamed to 'rseq',
       'seqList' renamed to 'evalList', 'seqPair' renamed to
       'evalTuple2',

    The naming scheme is now as follows:

      * Basic polymorphic strategies (of type @'Strategy' a@) are called @r...@.
        Examples: 'r0', 'rseq', 'rpar', 'rdeepseq'.

      * A strategy combinator for a particular type constructor
        or constructor class @T@ is called @evalT...@, @parT...@ or @seqT...@.

      * The @seqT...@ combinators (residing in module
         "Control.Seq") yield sequential strategies.
         Thus, @seqT...@ combinators cannot spark, nor can the sequential
         strategies to which they may be applied.
         Examples: 'seqTuple2', 'seqListN', 'seqFoldable'.

      * The @evalT...@ combinators do not spark themselves, yet they may
         be applied to strategies that do spark. (They may also be applied
         to non-sparking strategies; however, in that case the corresponding
         @seqT...@ combinator might be a better choice.)
         Examples: 'evalTuple2', 'evalListN', 'evalTraversable'.

      * The @parT...@ combinators, which are derived from their @evalT...@
         counterparts, do spark. They may be applied to all strategies,
         whether sparking or not.
         Examples: 'parTuple2', 'parListN', 'parTraversable'.

      * An exception to the type driven naming scheme are 'evalBuffer' and
         'parBuffer', which are not named after their type constructor (lists)
         but after their function (rolling buffer of fixed size).
    -}