反引号作为语法运算符

Rus*_*ott 1 haskell

刚刚遇到了一些对我来说似乎很奇怪的事情。反引号的功能类似于语法运算符。

applyOp :: Int -> (Int -> Int -> Int) -> Int -> Int
applyOp x op y = x `op` y

>  applyOp 2 (+) 5
7
Run Code Online (Sandbox Code Playgroud)

看到这一点我很惊讶。我一直认为需要反引号来包围运算符符号或标识符,而不是可以在执行期间绑定到运算符的标识符。我是否以错误的方式思考这个问题?

AJF*_*mar 6

反引号是将标识符转换为中缀运算符的语法糖。也就是说,a `f` b = f a b是一般的重写规则。这对于清晰起见很有用,但也可以避免太多括号,因为f (a b) (c d)可以重写为a b `f` c d.

然而,使用这些有一些注意事项,但只有两个限制:

  • 反引号表达式必须是标识符,因此1 `mod` 2有效,但a `zipWith (+)` b无效,因为它涉及函数应用。

  • 只有字母数字标识符可以反引号,因此1 `mod` 2有效,但1 `(+)` 2无效。您可以将此视为先前限制的应用。

  • 反引号表达式的优先级为 9,并且是左关联的,因此a `f` b `f` c被解析为(a `f` b) `f` c,并且一般其他运算符会包含它,因此a + c `f` b被解析为a + (c `f` b)*

在这种情况下,applyOp x op y = x `op` y是有效的,因为op是一个字母数字标识符,这相当于applyOp x op y = op x y。请注意,绑定模式匹配标识符没有限制!


*这对于标准 Prelude 运算符!!和来说是不正确的.有关优先级和固定性的更多信息可以在Haskell 98 报告中找到。

  • 小一点:除非您使用“-XHaskell98”(或使用不实现 Haskell 2010 的非 GHC 编译器)编译代码,否则您应该引用 Haskell 2010 报告(这是 GHC 使用的默认语义)- 2010 和'98 基本相同,但存在一些细微差异,可能会导致一些混乱。(2010 年唯一缺少的是 98 年出现的“n+k”模式,无论如何,这被广泛认为是一个错误特征)。 (3认同)