Reputation: 41
I'm trying to understand how paralleling in Haskell works and I've found following example in Control.Parallel docs.
import Control.Parallel
-- Equation for the upper hemisphere of the unit circle
circle :: Double -> Double
circle x = sqrt (abs(1 - x^2))
-- Calculate the area of a right-handed Riemann rectangle
area :: Double -> Double -> Double
area x1 x2 = (x2 - x1) * circle x2
-- Recursively add the areas of the Riemann rectangles
parEstimate :: [Double] -> Double
parEstimate (x:[]) = 0
parEstimate (x:y:[]) = area x y
parEstimate (x:y:xs) =
smaller `par` (larger `pseq` smaller + larger)
where smaller = area x y
larger = parEstimate (y:xs)
But I couldn't find an explanation of how this recursion works: parEstimate (x:y:xs), cause all examples I've found contains only two arguments. That's why I cannot find out how to run this function. That's how I do:
main = print (parEstimate [1.0, 2.0])
but not sure, if it's correct. Also I would like to implement function calculating definite integral based on this example.
Upvotes: 0
Views: 425
Reputation: 531808
The recursion, essentially, is a simple fold
-like recursion scheme; if this were purely sequential, you might write it as
seqEstimate :: [Double] -> Double
seqEstimate (x:[]) = 0
seqEstimate (x:y:[]) = area x y
seqEstimate (x:y:xs) = smaller + larger
where smaller = area x y
larger = seqEstimate (y:xs)
(In fact, you would probably just use zipWith
instead: seqEstimate xs = sum (zipWith area xs (tail xs))
.)
The parallelized version is similar. This time, though, par
is used to indicate that the left-hand side (smaller
) can be evaluated in parallel with the right-hand side (pseq larger (smaller + larger)
). Whether or not the compiler chooses to do so, and regardless of whether smaller
completes before or after larger
, the sum of smaller + larger
will be correctly computed.
Upvotes: 3