Why does the pointfree version of this function look like this?
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 po开发者_开发问答int-free form looks like (sum .) . zipWith (*)
instead of sum . zipWith (*)
. Why is sum in brackets and have 2 composition operators?
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]
.
KennyTM's answer is excellent, but still I'd like to offer another perspective:
dotProduct = (.) (.) (.) sum (zipWith (*))
(.) f g
appliesf
on the result ofg
given one argument(.) (.) (.) f g
appliesf
on the result ofg
given two arguments(.) (.) ((.) (.) (.)) f g
appliesf
on the result ofg
given three arguments- ...
- Can do
(.~) = (.) (.) (.)
,(.~~) = (.) (.) (.~)
,(.~~~) = (.) (.) (.~~)
and nowlet foo a b c d = [1..5]; (.~~~) sum foo 0 0 0 0
results in15
.- But I wouldn't do it. It will probably make code unreadable. Just be point-full.
- Conal's
TypeCompose
provides a synonym for(.)
calledresult
. 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.
- Conal's concept of "fusion" (not to be confused with other usages of "fusion") is kind of related and imho offers a nice way to compose functions. More details in this long Google Tech Talk that Conal gave
精彩评论