Consider the type of flip
and function composition:
flip :: (a -> b -> c) -> b -> a -> c
(.) :: (b -> c) -> (a -> b) -> a -> c
Now you can either apply (.)
to flip
or else apply flip
to (.)
.
In the first case:
(flip .)
-- is the same as
(.) flip
-- i.e. you are applying (.) to flip
Hence you get:
flip :: (a -> b -> c) -> b -> a -> c
|___________| |___________|
| |
(.) :: b c -> (a -> b) -> a -> c
-- Hence:
(flip .) :: (a -> a1 -> b -> c) -> a -> b -> a1 -> c
(.) flip :: (a -> a1 -> b -> c) -> a -> b -> a1 -> c
In the second case:
(flip (.))
-- is the same as
flip (.)
-- i.e. you are applying flip to (.)
Hence you get:
(.) :: (b -> c) -> (a -> b) -> a -> c
|______| |______| |______|
| | |
flip :: a b c -> b -> a -> c
-- Hence:
(flip (.)) :: (a -> b) -> (b -> c) -> a -> c
flip (.) :: (a -> b) -> (b -> c) -> a -> c
The problem is that when you write (flip .)
Haskell assumes that it is a section. Hence it considers flip
as an argument since .
is an operator. To treat an operator as a function you need to parenthesize it. Hence (flip (.))
is treated as applying flip
to (.)
. In this case the extra set of parentheses are not required. You can simply write it as flip (.)
.