A strategy can specify parallelism and sequencing as well as evaluation degree. Strategies specifying data-oriented parallelism describe the dynamic behaviour in terms of some data structure. For example parList is similar to seqList, except that it applies the strategy to every element of a list in parallel.
parList :: Strategy a -> Strategy [a] parList strat  = () parList strat (x:xs) = strat x `par` (parList strat xs)
Data-oriented strategies are applied by the using function which applies the strategy to the data structure x before returning it. The expression x `using` s is a projection on x, i.e. it is both a retraction (x `using` s is less defined than x) and idempotent ((x `using` s) `using` s = x `using` s). The using function is defined to have a lower precedence than any other operator because it acts as a separator between algorithmic and behavioural code.
using :: a -> Strategy a -> a using x s = s x `seq` x
A strategic version of the parallel map encountered in Section * can be written as follows. Note how the algorithmic code map f xs is cleanly separated from the strategy. The strat parameter determines the dynamic behaviour of each element of the result list, and hence parMap is parametric in some of its dynamic behaviour. Such strategic functions can be viewed as a dual to the algorithmic skeleton approach [Cole, 1988], and this relationship is discussed further in Section *.
parMap :: Strategy b -> (a -> b) -> [a] -> [b] parMap strat f xs = map f xs `using` parList strat