Given a Haskell function func :: a -> b -> c
, we can produce a function flippedFunc :: b -> a -> c
easily using flip
from Prelude.
One of my favorite ways to explain flip
uses the fact that because the function arrow (->)
associates to the right, we can rewrite the type signature as:
This indicates a transformation from one function into another function, with the order of the first two arguments reversed.
However, what if we want an arbitrary reordering of function arguments? There’s actually a straightforward (if messy) recipe to produce reorderings using just flip
and composition (.)
, but it requires understanding a few rules.
First, flip
by itself only swaps the first two arguments. Doing two flips in a row flip (flip f)
is idempotent, meaning a double flip has no effect on f
’s behavior.
For the following examples, let’s use this three-argument function f
and four-argument function g
:
We know that flip f
swaps the first two arguments:
Two flips in a row does nothing.
That do-nothing example can also be written as a chain of function composition:
If we want to swap arguments other than the first two, we need to compose. For example, to swap the second and third argument, we use flip . f
However, we’ve already seen that flip . flip . f
takes us back to doing nothing. If we wanted to swap the third and fourth arguments of some four-argument function g
, we’d need to nest compositions.
Here’s a listing of how we can generate all the possible argument order permutations of f
:
f
:: a -> b -> c -> d
flip . f
:: a -> c -> b -> d
flip f
:: b -> a -> c -> d
flip . flip f
:: b -> c -> a -> d
flip . flip (flip . flip f)
:: c -> a -> b -> d
flip (flip . flip f)
:: c -> b -> a -> d
We can use these flipped functions to do certain things, like partial application of arbitrary arguments.
thirdArgApplied :: a -> b -> d
thirdArgApplied = flip . flip (flip . flip f) $ c
where c = someDefaultArgument
Say we had a massive 25-argument function:
alphabet :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j ->
k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v ->
w -> x -> y -> z
We can swap arbitrary pairs of arguments. Here’s how to flip x
and y
in alphabet
:
((((((((((((((((((((((flip .) .) .) .) .) .) .) .) .)
.) .) .) .) .) .) .) .) .) .) .) .) .) . alphabet
Of course, what this all means is that we can do arbitrary manipulations of argument orderings, no matter how convoluted. Here’s an example where I’ve additionally used $
(instead of just parentheses, flip
, and .
) for…um…readability:
((((((((((((((((flip.).).).).).).).).).).).).).).).)$(((((((
((((((((((flip.).).).).).).).).).).).).).).).).)$(((((((((((
(((((((flip.).).).).).).).).).).).).).).).).).)$((((((((((((
(((((((flip.).).).).).).).).).).).).).).).).).).)$((((((((((
((((((((((flip.).).).).).).).).).).).).).).).).).).).)$(((((
((((((((((((((((flip.).).).).).).).).).).).).).).).).).).).)
.)$((((((((((((((((((((((flip.).).).).).).).).).).).).).).).
).).).).).).)$(((((((((((((((((((((((flip.).).).).).).).).).
).).).).).).).).).).).).).)$(((((((((((((((flip.).).).).).).
).).).).).).).).)$((((((((((((((((flip.).).).).).).).).).).)
.).).).).)$(((((((((((((((((flip.).).).).).).).).).).).).).)
.).).)$((((((((((((((((((flip.).).).).).).).).).).).).).).).
).).)$(((((((((((((((((((flip.).).).).).).).).).).).).).).).
).).).)$((((((((((((((flip.).).).).).).).).).).).).).)$(((((
((((((((flip.).).).).).).).).).).).).)$((((((((((((((flip.).
).).).).).).).).).).).).)$(((((((((((((((flip.).).).).).).).
).).).).).).).)$((((((((((((((((flip.).).).).).).).).).).).)
.).).).)$(((((((((((((((((flip.).).).).).).).).).).).).).).)
.).)$((((((((((((((((((flip.).).).).).).).).).).).).).).).).
).)$(((((((((((((((((((flip.).).).).).).).).).).).).).).).).
).).)$((((((((((((((((((((flip.).).).).).).).).).).).).).).)
.).).).).)$(((((((((((((((((((((flip.).).).).).).).).).).).)
.).).).).).).).).)$((((((((((((((((((((((flip.).).).).).).).
).).).).).).).).).).).).).).)$(((((((((((((((((((((((flip.).
).).).).).).).).).).).).).).).).).).).).).)$((((((((((((flip
.).).).).).).).).).).).)$(((((((((((((flip.).).).).).).).).)
.).).).)$((((((((((((((flip.).).).).).).).).).).).).).)$((((
(((((((((((flip.).).).).).).).).).).).).).).)$((((((((((((((
((flip.).).).).).).).).).).).).).).).)$(((((((((((((((((flip
.).).).).).).).).).).).).).).).).)$(((((((((((flip.).).).).)
.).).).).).)$((((((((((((flip.).).).).).).).).).).).)$((((((
(((((((flip.).).).).).).).).).).).).)$((((((((((((((flip.).)
.).).).).).).).).).).).)$(((((((((((((((flip.).).).).).).).)
.).).).).).).)$((((((((((((((((flip.).).).).).).).).).).).).
).).).)$(((((((((((((((((flip.).).).).).).).).).).).).).).).
).)$((((((((((((((((((flip.).).).).).).).).).).).).).).).).)
.)$(((((((((((((((((((flip.).).).).).).).).).).).).).).).).)
.).)$((((((((((((((((((((flip.).).).).).).).).).).).).).).).
).).).).)$(((((((((((((((((((((flip.).).).).).).).).).).).).
).).).).).).).).)$(((((((((flip.).).).).).).).).)$((((((((((
flip.).).).).).).).).).)$(((((((((((flip.).).).).).).).).).)
.)$((((((((((((flip.).).).).).).).).).).).)$(((((((((((((
flip.).).).).).).).).).).).).)$((((((((((((((flip.).).).).)
.).).).).).).).).)$(((((((((((((((flip.).).).).).).).).).).)
.).).).)$((((((((((((((((flip.).).).).).).).).).).).).).).).
)$(((((((((((((((((flip.).).).).).).).).).).).).).).).).)$((
((((((((((((((((flip.).).).).).).).).).).).).).).).).).)$(((
(((((flip.).).).).).).).)$(((((((flip.).).).).).).)$((((((((
flip.).).).).).).).)$(((((((((flip.).).).).).).).).)$(((((((
(((flip.).).).).).).).).).)$(((((((((((flip.).).).).).).).).
).).)$((((((((((((flip.).).).).).).).).).).).)$((((((flip.).
).).).).)$(((((((flip.).).).).).).)$(((((flip.).).).).)$((((
((flip.).).).).).)$(((((((flip.).).).).).).)$((((((((flip.).
).).).).).).)$(((((((((flip.).).).).).).).).)$((((((((((flip
.).).).).).).).).).)$((((flip.).).).)$(((((flip.).).).).)$((
((((flip.).).).).).)$(((((((flip.).).).).).).)$((((((((flip.
).).).).).).).)$(((((((((flip.).).).).).).).).)$((((((((((
flip.).).).).).).).).).)$(((((((((((flip.).).).).).).).).).)
.)$((((((((((((flip.).).).).).).).).).).).)$(((((((((((((
flip.).).).).).).).).).).).).)$((((((((((((((flip.).).).).).
).).).).).).).).)$(((((((((((((((flip.).).).).).).).).).).).
).).).)$((((((((((((((((flip.).).).).).).).).).).).).).).).)
$(((((((((((((((((flip.).).).).).).).).).).).).).).).).)$(((
(((((((((((((((flip.).).).).).).).).).).).).).).).).).)$((((
(((((((((((((((flip.).).).).).).).).).).).).).).).).).).)$((
(flip.).).)$((((flip.).).).)$(((((flip.).).).).)$((((((flip.
).).).).).)$(((((((flip.).).).).).).)$((((((((flip.).).).).)
.).).)$(((((((((flip.).).).).).).).).)$((((((((((flip.).).).
).).).).).).)$(((((((((((flip.).).).).).).).).).).)$((((((((
((((flip.).).).).).).).).).).).)$(((((((((((((flip.).).).).)
.).).).).).).).)$((((((((((((((flip.).).).).).).).).).).).).
).)$(((((((((((((((flip.).).).).).).).).).).).).).).)$((((((
((((((((((flip.).).).).).).).).).).).).).).).)$((flip.).)$((
(flip.).).)$((((flip.).).).)$(((((flip.).).).).)$(flip.)$((
flip.).)$(((flip.).).)$((((flip.).).).)$(((((flip.).).).).)$
((((((flip.).).).).).)$(((((((flip.).).).).).).)$flip$(flip.
)$((flip.).)$(((flip.).).)$((((flip.).).).)$(((((flip.).).).
).)$((((((flip.).).).).).)$(((((((flip.).).).).).).)$(((((((
(flip.).).).).).).).)$(((((((((flip.).).).).).).).).)$((((((
((((flip.).).).).).).).).).)$(((((((((((flip.).).).).).).).)
.).).)$((((((((((((flip.).).).).).).).).).).).)$((((((((((((
(flip.).).).).).).).).).).).).)$((((((((((((((flip.).).).).)
.).).).).).).).).)$(((((((((((((((flip.).).).).).).).).).).)
.).).).)$((((((((((((((((flip.).).).).).).).).).).).).).).).
)$(((((((((((((((((flip.).).).).).).).).).).).).).).).).)$((
((((((((((((((((flip.).).).).).).).).).).).).).).).).).)
alphabet
This is a (thoroughly) flipped-around version of alphabet
, with the type signature: