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

时间:2010-12-29 10:48:05

标签: haskell functional-programming

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

实施例。我有一个二进制函数,如:

sub :: Int -> Int -> Int
sub x y = x - y 

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

mapSubFrom5 x = map (sub 5) x

*Main> mapSubFrom5 [1,2,3,4,5]
[4,3,2,1,0]

如果我想绑定前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]

或者使用lambda:

mapSub5 x = map (\x -> sub x 5) x

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

3 个答案:

答案 0 :(得分:32)

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

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

首先,它只是

sub = (-)

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

addOne = (1 +)

......和第二个

half = (/ 2)

因此您的代码变为

map (-5) [1..5]

不幸的是,-5是一个数字文字,但你明白了。 :)现在我们可以通过在

中添加反引号来将任何函数转换为二元运算符
f x y == x `f` y

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

map (`sub` 5) [1..5]

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

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

答案 1 :(得分:9)

如何绑定第二个参数:

div2 = flip div 2

ghci> div2 10
5

在你的情况下,你可以写

ghci> map (flip (-) 5) [1..5]
[-4,-3,-2,-1,0]

请注意,在Haskell中,您可以将前缀形式的运算符编写为(-)。它与您问题中的sub相同。

答案 2 :(得分:9)

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

mapSub5 x = map (`sub` 5) x