“中缀表达式”是如何工作的?

28

我正在尝试使用 infixrinfixlinfix 声明。我理解了如何使用 infixrinfixl

-- Test expression: 40 +++ 20 +++ 50 +++ 10 * 10

-- infixr 8 +++ -- Calculated as: (40 +++ (20 +++ (50 +++ 10))) * 10. Result: 630.
-- infixl 8 +++ -- Calculated as: (((40 +++ 20) +++ 50) +++ 10) * 10. Result: 800.

-- infixr 6 +++ -- Calculated as: 40 +++ (20 +++ (50 +++ (10 * 10))). Result: 75.
-- infixl 6 +++ -- Calculated as: ((40 +++ 20) +++ 50) +++ (10 * 10). Result: 125.

(+++) :: Int -> Int -> Int
a +++ b = a + (b `div` 2)

但是我不理解 infix 关键字的工作原理。我想知道,使用 infix 关键字时是否总是需要用括号指定顺序?如果是这样,为什么数字参数是必要的,考虑到括号具有最高的优先级)?


4
结合一个运算符的多个副本时,结合性(l/r/<nothing>)说明如何分组;优先级(1-9)说明在存在多个不同运算符时如何进行分组。 - Daniel Wagner
2个回答

49

简介

rl指的是结合性,你指定的数字则是操作符优先级。如果你没有指定结合性,则得到的操作符只能通过显式括号或结合性非歧义地关联。

我们的测试数据结构

让我们使用一个数据结构来定义运算符并理解结合性的工作原理:

data Test = Test String deriving (Eq, Show)

它将包含使用以下运算符构建的字符串。

infixrinfixl 的结合性

现在让我们定义右关联和左关联运算符:

(>:) :: Test -> Test -> Test
(Test a) >: (Test b) = Test $ "(" ++ a ++ " >: " ++ b ++ ")"

(<:) :: Test -> Test -> Test
(Test a) <: (Test b) = Test $ "(" ++ a ++ " <: " ++ b ++ ")"

infixr 6 >:
infixl 6 <:

这些运算符通过显式地将括号添加到我们的相关术语中来构造结果运算符的字符串。

如果我们测试一下,就会发现它能正常工作:

print $ (Test "1") >: (Test "2") >: (Test "4")
-- Test "(1 >: (2 >: 4))"

print $ (Test "1") <: (Test "2") <: (Test "4")
-- Test "((1 <: 2) <: 4)"

关于 infix 的“结合性”

infix 声明并不指定结合性。那么在这种情况下会发生什么呢?让我们看一下:

(?:) :: Test -> Test -> Test
(Test a) ?: (Test b) = Test $ "(" ++ a ++ " ?: " ++ b ++ ")"

infix 6 ?:

现在让我们来试一下:

print $ (Test "1") ?: (Test "2") ?: (Test "4")

哎呀,我们遇到了一个问题:

先决条件解析错误 无法在同一中缀表达式中混合使用具有相同优先级的 `?:' [infix 6] 和 `?:' [infix 6]

正如您所看到的,语言解析器注意到我们没有指定运算符的结合性,不知道该怎么做。

如果我们改为删除最后一项:

print $ (Test "1") ?: (Test "2")
-- Test "(1 ?: 2)"

那么编译器就不会报错。

要修复原始术语,我们需要明确添加括号;例如:

print $ (Test "1") ?: ((Test "2") ?: (Test "4"))
-- Test "(1 ?: (2 ?: 4))"

演示


0

因为

1 +++ 2 < 3

运行良好。

1
Downvote - 请问这如何是一个信息丰富、经过深入研究的回答,并且为什么它不应该只是页面上某个晦涩的评论。 - toraritte
2
@toraritte:问题是:“既然括号具有最高优先级,为什么数字参数还是必要的?”这里有一个没有括号的表达式示例,因此需要运算符具有优先级。它很简短明了。如果您觉得这不太有用,那么完全在您的权利范围内。 - Ry-
1
问题是“中缀运算符如何工作?”,然后他们对此进行了扩展,最后提出了一些问题,可能是为了澄清他们的疑问。此外,我只是在浪费时间强调显而易见的事情,我应该去过自己的生活。 - toraritte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接