使用中缀函数的部分应用程序

sid*_*yll 12 haskell functional-programming currying partial-application operator-sections

虽然我对数学意义上的currying有一点了解,但部分应用中缀函数是一个新概念,我在深入研究" 了解你是一个很好的Haskell "一书后发现了这个概念.

鉴于此功能:

applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
Run Code Online (Sandbox Code Playgroud)

作者以一种有趣的方式使用它:

ghci> applyTwice (++ [0]) [1]  
[1,0,0]
ghci> applyTwice ([0] ++) [1]
[0,0,1]
Run Code Online (Sandbox Code Playgroud)

在这里我可以清楚地看到,结果函数传递了不同的参数,这不会通过正常的方式发生,因为它是一个curried函数(是吗?).那么,Haskell对中缀切片有什么特殊处理吗?它对所有中缀函数都是通用的吗?


作为旁注,这是我使用Haskell和函数式编程的第一周,我还在读这本书.

Ric*_* T. 18

是的,您可以通过指定其左侧或右侧操作数来部分应用中缀运算符,只需将另一个操作数留空(完全在您编写的两个示例中).

因此,([0] ++)(++) [0]或相同\x -> [0] ++ x(记住你可以通过括号将中缀运算符转换为标准函数),而(++ [0])等于\x -> x ++ [0].

了解反引号(``)的用法很有用,它可以让你在中缀运算符中用两个参数转换任何标准函数:

Prelude> elem 2 [1,2,3]
True
Prelude> 2 `elem` [1,2,3] -- this is the same as before
True
Prelude> let f = (`elem` [1,2,3]) -- partial application, second operand
Prelude> f 1
True
Prelude> f 4
False
Prelude> let g = (1 `elem`) -- partial application, first operand
Prelude> g [1,2]
True
Prelude> g [2,3]
False
Run Code Online (Sandbox Code Playgroud)

  • 我想把`(++)`想象成一个省略两个输入的部分. (4认同)

Don*_*art 15

是的,这是部分语法在起作用.

段被写为( op e )( e op ),其中op是二元运算符,e是表达式.对于二元运算符的部分应用,段是一种方便的语法.

以下身份包含:

(op e)  =   \ x -> x op e
(e op)  =   \ x -> e op x
Run Code Online (Sandbox Code Playgroud)


Car*_*arl 5

所有中缀运算符都可以在Haskell中的部分中使用 - 除了-由于一元否定的奇怪性.这甚至包括通过使用反引号转换为中缀的非中缀函数.您甚至可以考虑将操作员作为双面部分的正常功能的公式:

(x + y)- > (+ y)- >(+)

部分(主要是一些罕见的角落案例)被视为简单的lambdas.(/ 2)是相同的:

\x -> (x / 2)

并且与具有非交换运算符的示例(2 /)相同\x -> (2 / x).

理论上没有什么比这更令人感兴趣了.它只是部分应用中缀运算符的语法糖.它经常使代码变得更漂亮.(当然有反例.)

  • 请注意,"一元否定的奇怪性"是由于"( - 1)"应该被解释为数字文字-1还是函数`\ x - > x - 1`这一事实是不明确的.Haskell的创建者的选择是将其解释为数字文字,并提供函数`subtract`,它满足`subtract x =\y - > y - x`.它们还提供`negate`作为一元减函数,即`negate x = -x` (3认同)