[英]Haskell: Purpose of the flip function?
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
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: 一个人不太可能在立即应用于两个或多个参数的函数上使用
flip
函数,但flip
在两种情况下有用:
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. foldl
适用于我们。 So we can use flip (-)
instead of writing out the whole lambda \\xy -> y - x
. 所以我们可以使用
flip (-)
而不是写出整个lambda \\xy -> y - x
。
Additionally, it can be useful to use flip
to partially apply a function to its second argument. 此外,使用
flip
将函数部分应用于其第二个参数可能很有用。 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: 例如,我们可以使用
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]
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. 有时候,人们不会在这种情况下使用
flip
,而是使用中缀语法,因为操作符部分具有唯一属性,可以为函数提供第一个或第二个参数。 Therefore, writing (`f` x)
is equivalent to writing flip fx
. 因此,写
(`f` x)
相当于写flip fx
。 Personally, I think writing flip
directly is usually easier to read, but that's a matter of taste. 就个人而言,我认为直接书写
flip
通常更容易阅读,但这是一个品味问题。
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
. 但是你总是可以使用
let
表达式命名第一个参数计算,然后不使用flip
。
One very useful example of flip
usage is sorting in descending order. flip
使用的一个非常有用的示例是按降序排序。 You can see how it works in ghci
: 你可以在
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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.