10

The type of the Prelude function flip is:

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

I.e., it takes one binary function and two arguments.

The type of the Prelude function id is:

id :: a -> a

But the type of flip id is:

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

How is it possible to apply flip to id when id is a unary function and flip requires binary function for the first arg?

btw. flip id is similar to \ x f -> f x

Chris Conway
  • 55,321
  • 43
  • 129
  • 155
Tom Pažourek
  • 9,582
  • 8
  • 66
  • 107

2 Answers2

15

Haskell makes id fit the type of the first argument to flip by setting a = b -> c. So:

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

where id is taken to be of type

id :: (b -> c) ->  b -> c

which is equivalent to

id :: (b -> c) -> (b -> c)

i.e. a specialisation of id that only applies to unary functions.

Edit: I think I might rephrase my first line as:
Haskell deduces that id fits the type of the first argument to flip if a = b -> c.
In case that's any clearer.

Nefrubyr
  • 6,936
  • 2
  • 29
  • 20
4

Nefrubyr explains it very well.
Another way to (hopefully) make this a bit more intuitive is to think of the function application operator ($).

($) is a specialized form of id:

($) :: (a -> b) -> (a -> b)
($) = id

I've seen the definition (#) = flip ($), such that you can write the argument before the function its applied to: obj # show.

Obviously, since ($) is just a specialized form of id, you could also write: (#) = flip id

Tom Lokhorst
  • 13,658
  • 5
  • 55
  • 71