Haskell: Purpose of the flip function?

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.


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]