Question

I have a problem understanding the function composition and the concept of partially applied functions.

Actually I'm writing a small raytracer and have some example implemenentations which I dont understand exactly. Here is one example which I dont understand (https://github.com/ryanl/haskell-raytracer/blob/master/src/RayTracer.hs): It's the function which detects the color of a ray:

srdetectcolour' :: Scene -> Ray -> Maybe (Surface, Scalar) -> Colour
srdetectcolour' scene (Ray rx rv) (Just (s,d)) = zipWith (+) lightadded (surface_colour s)
where lightsvisible :: [Light]
      lightsvisible = lightsvisiblefrom intersectpoint scene
      lightadded :: Colour
      lightadded = (foldr (zipWith (+)) black . map effectivelight) lightsvisible
      effectivelight :: Light -> Colour
      effectivelight (v,c) = map (round . (*10000.0) . (/ (vector_sum ((intersectpoint - v) * (intersectpoint - v)))) . fromInteger) c
      intersectpoint = (rx + (mult d rv))

I'm interested in the (sub)-function lightadded where the foldr-part represents a partially applied function (when I'm right). The concept of the function is clear, one wants to add the light of visible lightsource in a point on a surface. For every visible lightsource there is a function effectivelight mapped over. What I dont understand is the last parameter of the foldr-function ( . map effectivelight) and the complete construction of the function. Can someone explain to me the function (in parts) and the construction of the function? Maybe one can write the function in a more intuitiv way?

Was it helpful?

Solution

That last part is not a parameter to foldr, but rather a function composition....

Let's break this apart:

lightadded :: Colour
lightadded = (foldr (zipWith (+)) black . map effectivelight) lightsvisible

The output of this is a Colour, and

foldr (zipWith (+)) black . map effectivelight

is therefore a function that takes lightsvisible as an input, and outputs a Colour.

Since infix operators bind more closely than anything else, this is actually two functions composed together (ie- . map effectivelight is not a parameter to the foldr)

foldr (zipWith (+)) black

and

map effectivelight

Notice that map effectivelight takes a list as input and gives one as output. lightvisible is an array, map effectivelight modifies each element in the list using effectivelight, and the result of this is actually the third parameter into the foldr.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top