我在理解函数组成和部分应用函数的概念时遇到了问题。
实际上我正在写一个小型光线跟踪器并有一些我不完全理解的示例实现。这是一个我不理解的例子(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)的最后一个参数以及函数的完整构造。有人可以向我解释功能(部分)和功能的构造吗?也许人们可以用更直接的方式编写函数?
答案 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的参数。