Reputation: 1732
I've been playing around with Haskell a fair bit, including practising writing functions in point-free form. Here is an example function:
dotProduct :: (Num a) => [a] -> [a] -> a
dotProduct xs ys = sum (zipWith (*) xs ys)
I would like to write this function in point-free form. Here is an example I found elsewhere:
dotProduct = (sum .) . zipWith (*)
However, I don't understand why the point-free form looks like (sum .) . zipWith (*)
instead of sum . zipWith (*)
. Why is sum in brackets and have 2 composition operators?
Upvotes: 14
Views: 819
Reputation: 24814
KennyTM's answer is excellent, but still I'd like to offer another perspective:
dotProduct = (.) (.) (.) sum (zipWith (*))
(.) f g
applies f
on the result of g
given one argument(.) (.) (.) f g
applies f
on the result of g
given two arguments(.) (.) ((.) (.) (.)) f g
applies f
on the result of g
given three arguments(.~) = (.) (.) (.)
, (.~~) = (.) (.) (.~)
, (.~~~) = (.) (.) (.~~)
and now let foo a b c d = [1..5]; (.~~~) sum foo 0 0 0 0
results in 15
.
TypeCompose
provides a synonym for (.)
called result
. Perhaps this name is more helpful for understanding what's going on.
fmap
also works instead of (.)
, if importing the relevant instances (import Control.Applicative
would do it) but its type is more general and thus perhaps more confusing.Upvotes: 14
Reputation: 523724
dotProduct xs ys = sum (zipWith (*) xs ys) -- # definition
dotProduct xs = \ys -> sum (zipWith (*) xs ys) -- # f x = g <=> f = \x -> g
= \ys -> (sum . (zipWith (*) xs)) ys -- # f (g x) == (f . g) x
= sum . (zipWith (*) xs) -- # \x -> f x == f
= sum . zipWith (*) xs -- # Precedence rule
dotProduct = \xs -> sum . zipWith (*) xs -- # f x = g <=> f = \x -> g
= \xs -> (sum .) (zipWith (*) xs) -- # f * g == (f *) g
= \xs -> ((sum .) . zipWith (*)) xs -- # f (g x) == (f . g) x
= (sum .) . zipWith (*) -- # \x -> f x == f
The (sum .)
is a section. It is defined as
(sum .) f = sum . f
Any binary operators can be written like this, e.g. map (7 -) [1,2,3] == [7-1, 7-2, 7-3]
.
Upvotes: 19