有没有一种快速简便的方法来发现GHCI中的函数的优先级和关联性?
我发现一种直接的方法是将一个操作符与另一个操作符强制组合,直到获得优先级解析错误(PPE)。例如,要发现!!
的优先级/关联性,我们可以为infix n
定义10个0 ≤ n < 10
的不同运算符:
>>> let infix 0 %; (%) = ($)
>>> undefined % undefined !! undefined
*** Exception: Prelude.undefined
>>> let infix 1 %; (%) = ($)
>>> undefined % undefined !! undefined
*** Exception: Prelude.undefined
[...]
>>> let infix 8 %; (%) = ($)
>>> undefined % undefined !! undefined
*** Exception: Prelude.undefined
>>> let infix 9 %; (%) = ($)
>>> undefined % undefined !! undefined
<interactive>:21:1:
Precedence parsing error
cannot mix `%' [infix 9] and `!!' [infixl 9] in the same infix expression
错误告诉您什么是先天性和固定性。由于定义的10个函数是非关联的,因此当优先级相等时,不可能避免PPE。天真的方法是尝试每个关联性的10个函数,给出一个20的WCET(因为如果你开始与目标相同的关联性,那个具有该关联性的10将会通过,但是一旦你到达那个失败就会发生下一个关联性的kth
优先级,其中k
是目标函数的优先级。)
但有更快的方法吗?我认为你可以做二分,平均实现log(10)步骤。例如,如果目标是!!!
,其定义为!!
,但infixl 6
,我们可以制作表达式(:[]) % "AB" !!! 1
,其中%
是其中之一相同的10个虚拟功能。如果%
的优先级太低而不能导致PPE,则表达式将产生"B"
(因为表达式将解析为(:[]) % ("AB" !!! 1)
),而如果优先级太高,它将yield ⊥
(因为表达式将解析为((:[]) % "AB") !!! 1
)。例如:
>>> let infixl 6 !!!; (!!!) = (!!)
>>> let infix 5 %; (%) = ($)
>>> (:[]) % "AB" !!! 1
"B"
>>> --too low
>>> let infix 7 %; (%) = ($)
>>> (:[]) % "AB" !!! 1
"*** Exception: Prelude.(!!): index too large
>>> --too high
>>> let infix 6 %; (%) = ($)
>>> (:[]) % "AB" !!! 1
<interactive>:10:1:
Precedence parsing error
cannot mix `%' [infix 6] and `!!!' [infixl 6] in the same infix expression
>>> --got it
但是,我不确定这种方法。
有人知道另一种方法吗?我可以想象可能有一种方法可以一步到位。但一小时后,我能想到的最好的就是这种二分法。
答案 0 :(得分:16)
是。您可以使用:info
命令。
Prelude> :info (+)
class Num a where
(+) :: a -> a -> a
...
-- Defined in `GHC.Num'
infixl 6 +
Prelude> :info (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in `GHC.Base'
infixr 9 .
Prelude> :info ($)
($) :: (a -> b) -> a -> b -- Defined in `GHC.Base'
infixr 0 $
如果它没有说,则默认为infixl 9
。
答案 1 :(得分:15)
@kqr的答案显然是来自GHCi的最佳答案,但我只是注意到是类似于你尝试过的快速方式,我有时会在lambdabot的IRC频道中使用它(其中)不支持:info
)。
>>> (0$0 !!)
由于部分要求(expr `op`)
只能在expr `op` var
与(expr) `op` var
完全相同地解析,以及$
与最低固定性正确关联时才能使用!!
无论!!
的固定性如何,永远不会解析,并会在错误消息中为您提供{{1}}的固定性。