Reputation: 49
Given the following functions for evalPair
, parPair
and deepSeq
respectively,
evalPair :: Strategy a -> Strategy b -> Strategy (a,b)
evalPair sa sb (a,b) = do
a' <- sa a
b' <- sb b
return (a',b')
parPair :: Strategy a -> Strategy b -> Strategy (a,b)
parPair sa sb = evalPair (rparWith sa) (rparWith sb)
rdeepseq :: NFData a => Strategy a
rdeepseq x = rseq (force x)
The question is why will the following code be evaluated in parallel as the author claims?
parPair rdeepseq rdeepseq :: (NFData a, NFData b) => Strategy (a,b)
I am in dount since Simon Marlow says the following
To break down what happens when this
Strategy
is applied to a pair:parPair
callsevalPair
, andevalPair
callsrparWith rdeepseq
on each component of the pair. So the effect is that each component will be fully evaluated to normal form in parallel.
According to what I see rparWith rdeepseq
is informally rpar . rseq . force
which means the argument will be evaluated to normal form, which it will be evaluated with rseq
sequentially, and hence in the end the rpar
is of no use in a parallel context.
Everything is taken from Simon Marlow's book.
Thanks in advance.
Upvotes: 2
Views: 342
Reputation: 105876
Let's have a look at parPair rdeepseq rdeepseq
:
parPair rdeepseq rdeepseq (a,b)
= evalPair (rparWith rdeepseq) (rparWith rdeepseq) (a,b)
= do
a' <- rparWith rdeepseq a
b' <- rparWith rdeepseq b
return (a', b')
Since rparWith
sparks it arguments, rdeepseq a
will be evaluated in parallel (possibly). It wouldn't be in parallel, if you were to use
evalPair rdeepseq rdeepseq
instead. The rparWith
is essential, as it sparks its argument for evaluation with the given strategy.
Upvotes: 4