在阅读了an awesome site中关于高阶函数的页面后,我仍然无法理解与函数组合成对的negate函数。
更具体地说,以这段代码为例:
ghci> map (negate . sum . tail) [[1..5],[3..6],[1..7]]这会产生:
[-14,-15,-27] 我又重新读了一遍这个页面,但老实说,我仍然不知道这行代码是如何产生这个答案的,如果有人能带我完成这个过程,我会非常感激!
发布于 2013-06-27 02:31:08
map f [a,b,c] = [f a, f b, f c]因为map f (x:xs) = f x:map f xs -将f应用于列表的每个元素。
所以
map (negate.sum.tail) [[1..5],[3..6],[1..7]]
= [(negate.sum.tail) [1..5], (negate.sum.tail) [3..6], (negate.sum.tail) [1..7]]现在
(negate . sum . tail) [1..5]
= negate (sum (tail [1,2,3,4,5]))
= negate (sum [2,3,4,5])
= negate 14
= -14因为(f.g) x = f (g x)和.是右关联的,所以(negate.sum.tail) xs = (negate.(sum.tail)) xs就是negate ((sum.tail) xs) = negate (sum (tail xs))。
除了列表的第一个元素之外,tail提供了所有内容:例如,tail (x:xs) = xs,例如tail "Hello" = "ello" sum按照您的期望将它们相加,以及
negate x = -x。
其他方法的工作原理类似,给出的是每个列表尾部的和。
发布于 2013-06-27 05:22:47
为了给AndrewC的优秀答案添加一个不同的视角,我通常会从functor laws和fmap的角度来考虑这些类型的问题。因为map可以被认为是fmap对列表的特化,所以我们可以用更通用的fmap替换map,并保留相同的功能:
ghci> fmap (negate . sum . tail) [[1..5],[3..6],[1..7]]现在我们可以应用合成函数律,使用代数替换来移动合成发生的位置,然后在列表中分别映射每个函数:
fmap (f . g) == fmap f . fmap g -- Composition functor law
fmap (negate . sum . tail) $ [[1..5],[3..6],[1..7]]
== fmap negate . fmap (sum . tail) $ [[1..5],[3..6],[1..7]]
== fmap negate . fmap sum . fmap tail $ [[1..5],[3..6],[1..7]]
== fmap negate . fmap sum $ fmap tail [[1..5],[3..6],[1..7]]
== fmap negate . fmap sum $ [tail [1..5],tail [3..6],tail [1..7]] -- As per AndrewC's explanation
== fmap negate . fmap sum $ [[2..5],[4..6],[2..7]]
== fmap negate $ [14, 15, 27]
== [-14, -15, -27]https://stackoverflow.com/questions/17327742
复制相似问题