Haskell:部分应用函数,光线跟踪器程序中的函数组合

时间:2014-01-01 16:49:29

标签: haskell raytracing function-composition partial-application

我在理解函数组成和部分应用函数的概念时遇到了问题。

实际上我正在写一个小型光线跟踪器并有一些我不完全理解的示例实现。这是一个我不理解的例子(https://github.com/ryanl/haskell-raytracer/blob/master/src/RayTracer.hs):它是检测光线颜色的函数:

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))

我对(sub)-function lightadded感兴趣,其中foldr - 部分代表部分应用的函数(当我是对的时候)。功能的概念很明确,人们希望在表面上的点上添加可见光源的光。对于每个可见光源,都会映射一个函数effectivelight。我不理解的是foldr - 函数(.map effectivelight)的最后一个参数以及函数的完整构造。有人可以向我解释功能(部分)和功能的构造吗?也许人们可以用更直接的方式编写函数?

1 个答案:

答案 0 :(得分:4)

最后一部分不是折叠器的参数,而是函数组合......

让我们分开:

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

这是一个颜色和

的输出
foldr (zipWith (+)) black . map effectivelight
因此,

是一个以lightsvisible作为输入并输出颜色的函数。

由于中缀运算符绑定比其他任何东西都更紧密,这实际上是两个函数组合在一起(即. map effectivelight不是foldr的参数)

foldr (zipWith (+)) black

map effectivelight

请注意map effectivelight将列表作为输入并将其作为输出。 lightvisible是一个数组,map effectivelight使用effectivelight修改列表中的每个元素,其结果实际上是第三个进入foldr的参数。