Если функция передается в другом порядке более высокого порядка, нельзя просто изменить аргументы на сайте вызова, поскольку сайт вызова находится в другой функции! Например, эти два выражения дают очень разные результаты:
ghci> foldl (-) 0 [1, 2, 3, 4]
-10
ghci> foldl (flip (-)) 0 [1, 2, 3, 4]
2
В этом случае мы не можем поменять местами аргументы (-)
, потому что мы не применяем (-)
напрямую; foldl
применяет это для нас. Таким образом, мы можем использовать flip (-)
вместо записи всей лямбды \x y -> y - x
.
Кроме того, может быть полезно использовать flip
, чтобы частично применить функцию ко второму аргументу. Например, мы могли бы использовать flip
, чтобы написать функцию, которая строит бесконечный список, используя функцию построителя, которая предоставляет индекс элемента в списке:
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]
Возможно, чаще, это используется, когда мы хотим частично применить второй аргумент функции, которая будет использоваться более высокого порядка, как в первом примере:
ghci> map (flip map [1, 2, 3]) [(+ 1), (* 2)]
[[2,3,4],[2,4,6]]
Иногда вместо использования flip
в подобном случае люди используют вместо этого инфиксный синтаксис, поскольку операторные секции имеют уникальное свойство, которое они могут предоставить первым или Второй аргумент функции. Следовательно, запись (`f` x)
эквивалентна записи flip f x
. Лично я думаю, что написание flip
напрямую легче читать, но это дело вкуса.