我之前已经问过这个问题,但是似乎我表达得太狭窄了。让我们看看我是否能解释一下我真正想要的。
假设我有某种类型,支持几个二元运算符,每个运算符具有不同的优先级和结合性。如何编写一个正确括号子表达式的 Show
实例?
我知道我在这里很愚钝,但是每次我尝试做到这一点时,我都会做错。一定有一些机械的步骤可以使这个程序正确工作,但我无法找到它。有人能给我举个例子吗?
我知道这最终归结为用 showParen
包装所有内容,并使用正确的魔术数字使用 showsPrec
显示子表达式,我可以使其 几乎 工作,但在 所有 情况下都不完全正确。
编辑: 考虑以下代码
data Expr =
Const Int |
Expr :+: Expr |
Expr :-: Expr |
Expr :*: Expr |
Expr :/: Expr
infixl 6 :+:
infixl 6 :-:
infixl 7 :*:
infixl 7 :/:
instance Show Expr where
showsPrec p e0 =
case e0 of
Const n -> shows n
x :+: y -> showParen (p > 6) $ (showsPrec 6 x) . (" :+: " ++) . (showsPrec 6 y)
x :-: y -> showParen (p > 6) $ (showsPrec 6 x) . (" :-: " ++) . (showsPrec 6 y)
x :*: y -> showParen (p > 7) $ (showsPrec 7 x) . (" :*: " ++) . (showsPrec 7 y)
x :/: y -> showParen (p > 7) $ (showsPrec 7 x) . (" :/: " ++) . (showsPrec 7 y)
这个几乎正确地工作:
*Main> Const 1 :+: Const 2 :*: Const 3 :+: Const 4
1 :+: 2 :*: 3 :+: 4
*Main> (Const 1 :+: Const 2) :*: (Const 3 :+: Const 4)
(1 :+: 2) :*: (3 :+: 4)
但还不完全一样:
*Main> Const 1 :+: Const 2 :-: Const 3 :-: Const 4
1 :+: 2 :-: 3 :-: 4
*Main> Const 1 :+: Const 2 :-: (Const 3 :-: Const 4)
1 :+: 2 :-: 3 :-: 4
看起来优先级没问题,但是结合性有问题。