9

I am a bit surprised that this was not asked before. Maybe it is a stupid question.

I know that flip is changing the order of two arguments.

Example:

(-) 5 3
= 5 - 3
= 2

flip (-) 5 3
= 3 - 5
= -2

But why would I need such a function? Why not just change the inputs manually?

Why not just write:

(-) 3 5
= 3 - 5
= -2
Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
simplesystems
  • 839
  • 2
  • 14
  • 28

3 Answers3

20

One is unlikely to ever use the flip function on a function that is immediately applied to two or more arguments, but flip can be useful in two situations:

  1. If the function is passed higher-order to a different function, one cannot simply reverse the arguments at the call site, since the call site is in another function! For example, these two expressions produce very different results:

    ghci> foldl (-) 0 [1, 2, 3, 4]
    -10
    ghci> foldl (flip (-)) 0 [1, 2, 3, 4]
    2
    

    In this case, we cannot swap the arguments of (-) because we do not apply (-) directly; foldl applies it for us. So we can use flip (-) instead of writing out the whole lambda \x y -> y - x.

  2. Additionally, it can be useful to use flip to partially apply a function to its second argument. For example, we could use flip to write a function that builds an infinite list using a builder function that is provided the element’s index in the list:

    buildList :: (Integer -> a) -> [a]
    buildList = flip map [0..]
    
    ghci> take 10 (buildList (\x -> x * x))
    [0,1,4,9,16,25,36,49,64,81]
    

    Perhaps more frequently, this is used when we want to partially apply the second argument of a function that will be used higher-order, like in the first example:

    ghci> map (flip map [1, 2, 3]) [(+ 1), (* 2)]
    [[2,3,4],[2,4,6]]
    

    Sometimes, instead of using flip in a case like this, people will use infix syntax instead, since operator sections have the unique property that they can supply the first or second argument to a function. Therefore, writing (`f` x) is equivalent to writing flip f x. Personally, I think writing flip directly is usually easier to read, but that’s a matter of taste.

Alexis King
  • 43,109
  • 15
  • 131
  • 205
  • In your buildList example coludnt you just give a function to buildList like buildList f = map f [0..] – simplesystems Jul 01 '18 at 06:49
  • 1
    @simplesystems Yes, you can always write the same thing without `flip` by essentially just inlining the definition of `flip` at its use site. But using `flip` makes it possible to write in [point-free style](https://wiki.haskell.org/Pointfree), which some people find more readable, and some people don’t. Personally, I think it’s situational—I think sometimes point-free style eliminates noise and makes things easier to understand—but in that case, I agree, the version with the explicit argument is really no worse. – Alexis King Jul 01 '18 at 06:52
  • 1
    To put it another way, you can always replace `flip f` with `\x y -> f y x`, so `flip` is by no means essential! But like all functions, it is an abstraction, albeit a small one. – Alexis King Jul 01 '18 at 06:53
  • @simplesystems You might also be interested in https://stackoverflow.com/q/7402528/176841 . There is some theory you can explore here, if you want: in haskell `flip` lets us avoid using lambdas (for clarity, aesthetics); interestingly it turns out that lambdas are never _necessary_: it's possible to select a handful of functions ("combinators", such as `flip`), such that you have a system as powerful as the lambda calculus. This is called a _basis_, the most famous being the `SKI` combinator calculus. – jberryman Jul 01 '18 at 18:21
  • `flip` is usually named `C` and can form part of a basis too: https://en.wikipedia.org/wiki/B,_C,_K,_W_system .The point I'm trying to get at is that `flip` (and `const`, and `id`) is not arbitrary, but in fact you discover it in the theory if you're thinking about how you might express computation without resorting to lambdas (which is often a goal in haskell for clarity/aesthetic reasons, as described in other answers here) – jberryman Jul 01 '18 at 18:24
5

One very useful example of flip usage is sorting in descending order. You can see how it works in ghci:

ghci> import Data.List

ghci> :t sortBy 
sortBy :: (a -> a -> Ordering) -> [a] -> [a]

ghci> :t compare
compare :: Ord a => a -> a -> Ordering

ghci> sortBy compare [2,1,3]
[1,2,3]

ghci> sortBy (flip compare) [2,1,3]
[3,2,1]
Shersh
  • 9,019
  • 3
  • 33
  • 61
4

Sometimes you'll want to use a function by supplying the second parameter but take it's first parameter from somewhere else. For example:

map (flip (-) 5) [1..5]

Though this can also be written as:

map (\x -> x - 5) [1..5]

Another use case is when the second argument is long:

flip (-) 5 $
   if odd x
      then x + 1
      else x

But you can always use a let expression to name the first parameter computation and then not use flip.

soupi
  • 1,013
  • 6
  • 6
  • what is the $ standing for in you third example? – simplesystems Jul 01 '18 at 06:51
  • +1, I especially like your last example. I’ve definitely seen that at times (and I might have even written it myself once or twice) and it isn’t something I thought to include in my answer. :) – Alexis King Jul 01 '18 at 06:54
  • simplesystems, I use it instead of parentheses. You can read more about it here: https://haskell-lang.org/tutorial/operators – soupi Jul 01 '18 at 07:27
  • 1
    Alexis, yeah I found that this use case is more common for me! (I also prefer using backticks instead of flip in many cases). – soupi Jul 01 '18 at 07:30