After reading through a page on Higher Order Functions from an awesome site I am still having trouble understanding the negate function paired with function composition.
to be more specific, take this piece of code:
ghci> map (negate . sum . tail) [[1..5],[3..6],[1..7]]
which yields:
[-14,-15,-27]
I re-read the page again, but to be honest, I still have no idea how that line of code produced this answer, if someone could walk me through the process of this I would really appreciate it!
map f [a,b,c] = [f a, f b, f c]
because map f (x:xs) = f x:map f xs
- apply f
to each element of the list.
So
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]]
now
(negate . sum . tail) [1..5]
= negate (sum (tail [1,2,3,4,5]))
= negate (sum [2,3,4,5])
= negate 14
= -14
because (f.g) x = f (g x)
and .
is right associative, so (negate.sum.tail) xs = (negate.(sum.tail)) xs
which in turn is negate ((sum.tail) xs) = negate (sum (tail xs))
.
tail
gives you everything except the first element of a list: tail (x:xs) = xs
, for example tail "Hello" = "ello"
sum
adds them up as you expect, andnegate x = -x
.
The others work similarly, giving minus the sum of the tail of each list.
To add a different perspective to AndrewC's excellent answer I usually think about these types of problems in terms of the functor laws and fmap
. Since map
can be thought of as a specialization of fmap
to lists we can replace map
with the more general fmap
and keep the same functionality:
ghci> fmap (negate . sum . tail) [[1..5],[3..6],[1..7]]
Now we can apply the composition functor law using algebraic substitution to shift where the composition is happening and then map each function individually over the list:
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With