Sequential ordering of evaluation: Difference between revisions
mNo edit summary |
(Earlier quote added, existing quote replaced, formatting simplified) |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:Proposals]] | [[Category:Proposals]] | ||
The <code>seq</code> primitive, despite its name, is not required to evaluate its parameters in some predefined order, according to the Haskell 2010 Report. For | The <code>seq</code> primitive, despite its name, is not required to evaluate its parameters in some predefined order, according to the Haskell 2010 Report. For | ||
parallel programming, sometimes a variant of <code>seq</code> is needed with | parallel programming, sometimes a variant of <code>seq</code> is needed with | ||
such an ordering: | such an ordering: | ||
<blockquote> | |||
The <code>seq</code> combinator implements sequential composition. When the expression <code>e1 ‘seq‘ e2</code> is evaluated, <code>e1</code> | |||
is evaluated to weak head normal form first, and then the value of <code>e2</code> is returned. In the following parallel <code>nfib</code> | |||
function, <code>seq</code> is used to force the evaluation of <code>n2</code> before the addition takes place. This is because Haskell does not | |||
specify which operand is evaluated first, and if <code>n1</code> was evaluated before <code>n2</code>, there would be no parallelism. | |||
<haskell> | |||
nfib :: Int -> Int | |||
nfib n | n <= 1 = 1 | |||
| otherwise = n1 ‘par‘ (n2 ‘seq‘ n1 + n2 + 1) | |||
where | |||
n1 = nfib (n-1) | |||
n2 = nfib (n-2) | |||
</haskell> | |||
:<small>[https://web.archive.org/web/20040228202402/http://www.dcs.gla.ac.uk/fp/workshops/fpw96/Trinder.pdf Accidents always Come in Threes: A Case Study of Data-intensive Programs in Parallel Haskell] (page 2 of 14).</small> | |||
</blockquote> | |||
<blockquote> | |||
<b>2.1 The need for</b><code>pseq</code> | |||
The <code>pseq</code> combinator is used for sequencing; informally, it | |||
evaluates its first argument to weak-head normal form, and then evaluates | |||
its second argument, returning the value of its second argument. | |||
Consider this definition of <code>parMap</code>: | |||
<haskell> | |||
parMap f [] = [] | |||
parMap f (x:xs) = y ‘par‘ (ys ‘pseq‘ y:ys) | |||
where y = f x | |||
ys = parMap f xs | |||
</haskell> | |||
The intention here is to spark the evaluation of <code>f x</code>, and then | |||
evaluate <code>parMap f xs</code>, before returning the new list <code>y:ys</code>. The | |||
programmer is hoping to express an <i>ordering</i> of the evaluation: <i>first</i> | |||
spark <code>y</code>, <i>then</i> evaluate <code>ys</code>. | |||
:<small>[https://www.cs.tufts.edu/~nr/cs257/archive/simon-peyton-jones/multicore-ghc.pdf Runtime Support for Multicore Haskell] (page 2 of 12).</small> | |||
</blockquote> | |||
Instead of two or more similar primitives with similar purposes, extend the existing <code>seq</code> primitive with the traditional ordering of evaluation for its parameters - first, then second; with the role of simple strictness-control being performed by a new primitive with a more appropriate name e.g. | Instead of two or more similar primitives with similar purposes, extend the existing <code>seq</code> primitive with the traditional ordering of evaluation for its parameters - first, then second; with the role of simple strictness-control being performed by a new primitive with a more appropriate name e.g. |
Latest revision as of 05:28, 17 September 2024
The seq
primitive, despite its name, is not required to evaluate its parameters in some predefined order, according to the Haskell 2010 Report. For
parallel programming, sometimes a variant of seq
is needed with
such an ordering:
The
seq
combinator implements sequential composition. When the expressione1 ‘seq‘ e2
is evaluated,e1
is evaluated to weak head normal form first, and then the value ofe2
is returned. In the following parallelnfib
function,seq
is used to force the evaluation ofn2
before the addition takes place. This is because Haskell does not specify which operand is evaluated first, and ifn1
was evaluated beforen2
, there would be no parallelism. nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = n1 ‘par‘ (n2 ‘seq‘ n1 + n2 + 1) where n1 = nfib (n-1) n2 = nfib (n-2)
2.1 The need for
pseq
The
pseq
combinator is used for sequencing; informally, it evaluates its first argument to weak-head normal form, and then evaluates its second argument, returning the value of its second argument. Consider this definition ofparMap
: parMap f [] = [] parMap f (x:xs) = y ‘par‘ (ys ‘pseq‘ y:ys) where y = f x ys = parMap f xsThe intention here is to spark the evaluation of
f x
, and then evaluateparMap f xs
, before returning the new listy:ys
. The programmer is hoping to express an ordering of the evaluation: first sparky
, then evaluateys
.
- Runtime Support for Multicore Haskell (page 2 of 12).
Instead of two or more similar primitives with similar purposes, extend the existing seq
primitive with the traditional ordering of evaluation for its parameters - first, then second; with the role of simple strictness-control being performed by a new primitive with a more appropriate name e.g.
amid
, in Strictness without ordering, or confusion.
Atravers 02:00, 7 January 2019 (UTC)