如何在函数中绑定第二个参数而不是第一个参数(以优雅的方式)?

Fra*_*eld 37 haskell functional-programming

在没有使用lambda函数或定义另一个"本地"函数的情况下,Haskell中是否有一种方法可以绑定第二个参数而不是第一个函数?

例.我有一个像二进制函数:

sub :: Int -> Int -> Int
sub x y = x - y 
Run Code Online (Sandbox Code Playgroud)

现在,如果我想绑定第一个参数,我可以轻松地使用(sub someExpression):

mapSubFrom5 x = map (sub 5) x

*Main> mapSubFrom5 [1,2,3,4,5]
[4,3,2,1,0]
Run Code Online (Sandbox Code Playgroud)

如果我想绑定前n个参数而没有"gap",那就行得很好.

如果我想绑定第二个参数而不是第一个参数,我知道的两个选项更详细:

通过另一个本地功能:

mapSub5 x = map sub5 x
    where sub5 x = sub x 5

*Main> mapSub5 [1,2,3,4,5]
[-4,-3,-2,-1,0]
Run Code Online (Sandbox Code Playgroud)

或者使用lambda:

mapSub5 x = map (\x -> sub x 5) x
Run Code Online (Sandbox Code Playgroud)

虽然两者都工作正常,但我喜欢"sub 5"的优雅,并想知道是否有一种类似的优雅方式来绑定函数的第n(n> 1)个参数?

Dar*_*rio 33

flip,它产生了一个反转前两个参数的新函数,已经被提到作为一个直接的解决方案.

但是,值得注意的是Haskell为二元运算符定义了一个漂亮的中缀语法.

首先,它很简单

sub = (-)
Run Code Online (Sandbox Code Playgroud)

随着括号,所有运算符 - 通常也是 - 普通函数.现在我们可以用一些特殊的语法来操作运算符.绑定到第一个操作数:

addOne = (1 +)
Run Code Online (Sandbox Code Playgroud)

......到第二个

half = (/ 2)
Run Code Online (Sandbox Code Playgroud)

因此你的代码变成了

map (-5) [1..5]
Run Code Online (Sandbox Code Playgroud)

不幸的是,这-5是一个字面数字,但你明白了.:)现在我们可以将任何函数转换为二元运算符,方法是在其中添加反引号

f x y == x `f` y
Run Code Online (Sandbox Code Playgroud)

我们可以使用这种特殊的运算符语法来编写

map (`sub` 5) [1..5]
Run Code Online (Sandbox Code Playgroud)


注意:第一个参数的通用是常见的,第二个参数 - 就像你的情况一样 - 很可能.但是:我不会为了进一步的争论而这样做.Haskell函数是以一种风格编写的,正如那个原因,常见的咖喱都在前面.

使用一些特殊的语法来进一步论证对我来说太隐蔽了.只需使用lambda并为变量提供描述性名称.

  • 因为`-5`是一个数字,所以haskell制造商甚至添加了一个`subtract`函数,它定义为`subtract = flip( - )`,这样你就可以编写`map(减去5)`.但它更具可读性. (13认同)
  • 此外,最后一个注释的必然结果:如果您经常希望将后面的参数部分应用于您自己编写的函数,请不要犹豫直接更改订单!函数有三个或更多可能以这种方式使用的参数是相对罕见的. (3认同)

sas*_*nin 9

如何绑定第二个参数:

div2 = flip div 2

ghci> div2 10
5
Run Code Online (Sandbox Code Playgroud)

在你的情况下你可以写

ghci> map (flip (-) 5) [1..5]
[-4,-3,-2,-1,0]
Run Code Online (Sandbox Code Playgroud)

请注意,在Haskell中,您可以将前缀形式的运算符编写为(-).它和sub你的问题一样.


Ed'*_*'ka 9

对于n = 2,只有另一种绑定方式:

mapSub5 x = map (`sub` 5) x
Run Code Online (Sandbox Code Playgroud)