Pergunta

Consider:

:type (flip .)

(flip .) :: (a -> a1 -> b -> c) -> a -> b -> a1 -> c

I just can't figure out why. As I understand, flip has the following type:

flip :: (a -> b -> c) -> b -> a -> c

In addition (.) has the following type:

(.) :: (b1 -> c1) -> (a1 -> b1) -> a1 -> c1

Hence, unifying the types I get:

a = (b1 -> c1) -> (a1 -> b1)
b = a1

Which gives:

(flip .) :: a1 -> ((b1 -> c1) -> (a1 -> b1)) -> c1

Which is far from the actual type.

What am I doing wrong? Any sort of help would be appreciated.

Foi útil?

Solução

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 (.).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top