2

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.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
javag87
  • 61
  • 6
  • Your analysis gives the type for `flip (.)` which is very different from `flip .`. – Code-Apprentice May 13 '14 at 01:48
  • @Code-Guru: In fact flip (.) has type (a -> b) -> (b -> c) -> a -> c, so my reasoning is not even right for that case – javag87 May 13 '14 at 02:01
  • @amalloy: Indeed, it's a duplicate of that one. What should I do in this case? – javag87 May 13 '14 at 02:13
  • BTW your unification is wrong. How did you get `a = (b1 -> c1) -> (a1 -> b1)` and `b = a1`? You are trying to unify `a -> b -> c` with `(b1 -> c1) -> (a1 -> b1) -> a1 -> c1`. Hence you should get `a = b1 -> c1`, `b = a1 -> b1` and `c = a1 -> c1`. – Aadit M Shah May 13 '14 at 02:28
  • @javag87 You don't have to do anything. After a few people with enough reputation have agreed with me, this question will be closed and a prominent link will point to the question this is a duplicate of. – amalloy May 13 '14 at 02:46
  • @amalloy After which you may accept my answer. It's better than minitech's answer anyway. It has visual elements. – Aadit M Shah May 13 '14 at 03:00

1 Answers1

1

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

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • 1
    Good explanation, but does not `flip (.)` appy `flip` to `(.)` not the other way around? – Ingo May 13 '14 at 10:40
  • No, `flip (.)` applies `(.)` to `flip`. The argument is `(.)` and the argument is always applied to the function. In Haskell the function always comes before the argument. In most stack based languages like Forth the function comes after the arguments. Hence if you would write `add 2 3` in Haskell then you would write `2 3 add` in Forth. – Aadit M Shah May 13 '14 at 13:02
  • 1
    Beg to differ. For example, look here: http://hackage.haskell.org/package/base-4.7.0.0/docs/Prelude.html#v:map It reads "map f xs is the list obtained by applying f to each element of xs" - hence the function gets applied to some value, not the other way. – Ingo May 13 '14 at 13:07
  • 1
    I just read the Wikipedia page on lambda calculus and it does indeed state that function application is when a function is applied to a value. I have always been under the impression that it was the other way around. Thank you for clearing that up for me. I edited my answer to reflect the change. – Aadit M Shah May 13 '14 at 13:52