我正在使用infixr
,infixl
和infix
声明。我了解infixr
和infixl
的工作原理:
-- 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
您总是需要用括号指定顺序?如果是这样,为什么数字参数必须考虑括号具有最高优先级?
答案 0 :(得分:29)
r
和l
是指关联性,您指定的数字是指运算符优先级。如果不指定关联性,则会得到一个只能通过显式括号关联的运算符,或者当关联性不具有模糊性时。
让我们使用数据结构来定义运算符并理解关联性如何工作:
data Test = Test String deriving (Eq, Show)
它将包含使用以下运算符构建的字符串。
infixr
和infixl
现在让我们定义右关联运算符和左关联运算符:
(>:) :: 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")
Woops,我们得到:
优先解析错误 不能在同一个中缀表达式中混合`?:'[中缀6]和`?:'[中缀6]
正如您所看到的,语言解析器注意到我们没有指定运算符的关联性,也不知道该怎么做。
如果我们改为删除最后一个词:
print $ (Test "1") ?: (Test "2")
-- Test "(1 ?: 2)"
然后编译器不会抱怨。
要修复原始术语,我们需要明确添加括号;例如:
print $ (Test "1") ?: ((Test "2") ?: (Test "4"))
-- Test "(1 ?: (2 ?: 4))"
答案 1 :(得分:5)
由于
1 +++ 2 < 3
工作正常。