我正在从“了解Haskell带来的好处!”中学习高阶函数!由Miran Lipovaca撰写。我知道flip函数接受一个函数并返回一个与原始函数类似的函数,但是前两个参数被翻转。
我不完全了解以下带有map函数的示例的工作方式。
ghci> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]
Map接受一个函数并将其应用于列表的每个元素,从而生成一个新列表。但是由于函数map是带参数subtract 20 [1,2,3,4]
的flip,因此生成的函数为20 subtract [1,2,3,4]
吗?
我认为这是不正确的,因为仅当您键入subtract 1 20
时才会生成诸如19之类的值。我不确定在上面的示例中减法将如何工作以产生输出列表。
答案 0 :(得分:8)
否,这里的功能map :: (a -> b) -> [a] -> [b]
是(flip subtract 20)
,这是您传递给map
的参数。因此,这意味着:
map (flip subtract 20) [1,2,3,4]
等效于:
[flip subtract 20 1, flip subtract 20 2, flip subtract 20 3, flip subtract 20 4]
flip :: (a -> b -> c) -> b -> a -> c
是一个接受函数并翻转参数的函数。因此,flip subtract 20
在语义上等效于\x -> subtract x 20
。因此,我们的列表等效于:
[subtract 1 20, subtract 2 20, subtract 3 20, subtract 4 20]
subtract :: Num a => a -> a -> a
是(-)
的“翻转”版本,因此等效于:
[20 - 1, 20 - 2, 20 - 3, 20 - 4]
因此等同于:
Prelude> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]
因此,上述表达式的缩写是:
map (20 -) [1,2,3,4]
答案 1 :(得分:3)
flip
具有以下功能:它以相反的顺序(“翻转”)将给定功能应用于两个给定参数。
Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c
这就是(flip subtract 20)
变成函数f(x)= 20-x的方式,其中(subtract 20)
对应于g(x)= x-20。
然后,使用map函数将f应用于每个列表项。
答案 2 :(得分:3)
但是由于翻转是功能映射所需要的...
不。 map
将函数作为其第一个参数-这里是flip subtract 20
。正如我们现在所看到的,这确实是一个函数(如果不是,则编译器会引发错误,因为它在这里需要一个函数)。
我们将从subtract开始-实际上定义为flip (-)
。这意味着flip subtract
就是(-)
,或者:
flip subtract = \a b -> a - b
相对于
subtract = \a b -> b - a
因此,通过进行以下操作:
flip subtract a = \b -> a - b
并替换为20:
flip subtract 20 = \b -> 20 - b
所以flip subtract 20
确实是一个函数,它返回从20中减去其参数的结果。map
在给定的列表上使用此函数会显示结果。