A `Strategy` describes how a value should be evaluated, separately from the algorithm that computes it. In `Control.Parallel.Strategies`, it is a type synonym for `a -> Eval a`: a function that receives a value and returns an `Eval` action specifying evaluation work. This lets pure code keep its result and logic while adding a plan for sequential or parallel evaluation. section 13.4.2 section 13.5
Prebuilt strategies express common evaluation choices:
- `r0` performs no evaluation. section 13.4.2
- `rseq` evaluates an argument to weak head normal form: enough to reveal its first data constructor, without necessarily evaluating contained values. section 13.4.2
- `rpar` creates a spark, making an argument available for parallel evaluation by the runtime. section 13.4.2 section 13.4.3
- `rdeepseq` forces full evaluation to normal form, including data beneath the outer constructor. section 13.4.2
`Eval` collects the evaluation plan, and `runEval` retrieves its value. A spark created with `rpar` is only an opportunity for parallel work: it may fizzle if the caller demands the result before the spark finishes, or be a dud when the value was already evaluated. Haskell execution contexts take sparks from a shared pool through work stealing; runtime details such as garbage collection of unused sparks are handled automatically. section 13.4.3 section 13.4.3
Apply a strategy across a collection
`evalList` lifts a strategy for one element into a strategy for a list. For example, `map (^ 100) [1 .. 1000] \`using\` evalList rpar` maps first and requests parallel evaluation of the resulting elements. `withStrategy` provides the same idea in a function-style form. For vectors, creating a spark per pixel can overflow the spark pool; splitting a vector into larger chunks and applying `rseq` per chunk produces a practical parallel mapping strategy. section 13.4.3 section 13.4.3 section 13.4.3
Figure 13.5 Haskell execution contexts and spark pools
The execution-context diagram shows how `rpar` feeds sparks into a pool that available Haskell execution contexts can steal and evaluate. section 13.4.3
Evaluation strategies support deterministic parallelism: the algorithm remains unchanged while its evaluation order is made explicit. They work best when work is large enough to justify each spark. Too many tiny sparks can overflow the pool and reduce effectiveness, so divide collection work into larger chunks before evaluating those chunks in parallel. section 13.5 section 13.5
