flip id
. What's that do?id
is the identity function -- just returns its argument, so it has type a → a
.flip
converts a two-arg function to one that takes its args in the other order -- so, thinking it through, that's type (a → b → c) → (b → a → c)
(the parens on the right side aren't necessary but they add clarity.Those are straightforward enough -- but how do you flip a one-argument function? Let's just make the types work out. Start with
id
:id :: a → a
Substitute in a hypothetical function of type
x → y
in for a
. (I chose new letters to make it less confusing -- too many "a"s flying around already.)id :: (x → y) → (x → y)
Now remove the unnecessary parens on the right (since → is right-associative):
id :: (x → y) → x → y
We now have a function that could be interpreted as having two arguments!
Now let's stick that into
flip
. flip
's a
is now x → y
, its b
is x
, and its c
is y
, so:flip :: (a → b → c) → (b → a → c)
flip id :: (x → (x → y) → y)
And remove the unnecessary parens:
flip id :: x → (x → y) → y
And now with the type we can derive the function. Let's call it
flipid
:flipid x f = f x
And that is a simple function: it takes an argument and a function and calls the function with the argument. You could read it as flipping the implicit application operator; in fact, it has the same type as
flip ($)
, which really is flipping the application operator.But after all that I'm still not sure I would've come up with that on my own... ah, Haskell, no matter how much I learn there are always simple yet surprising corners. (Some other observations that might have helped:
id f x = f x
; f `id` x = f x
. Or, looking back, that id
is the application function, as evidenced by my two-arg form of id
.)