如何在haskell中更改构造函数的优先级



我正在做一个练习,为Maybe数据类型中的对象实现括号:
我想要实现的是这种括号:

-- MyJust 'a'
-- MyJust (MyJust 'a')
-- MyJust MyNothing
data MyMaybe a = MyNothing | MyJust a
instance Show a => Show (MyMaybe a) where
showsPrec _ MyNothing = showString "MyNothing"
showsPrec p (MyJust x) =
showParen(p>6)(showString "MyJust ".showsPrec 7 x)

我的代码可以工作,但有些地方我不理解。首先,MyJust运算符的优先级是多少(它必须小于6,否则我会得到类似(MyJust (MyJust 'a'))的东西?另一个问题是,例如,我如何将其更改为9,从而得到(MyJust (MyJust 'a'))?我尝试了infixl 9 'MyJust',但它不起作用。我问这个问题是为了更好地理解haskell中的优先级。

我认为您混淆了Haskell运算符的实际优先级与showsPrec使用的优先级跟踪方案,以确保可打印表示以正确的方式使用括号来匹配实际优先级。

在Haskell中,一个术语对另一个术语的"应用",无论是像sqrt 16这样的函数应用程序,还是像Just 4这样的构造函数应用程序,都始终有效地保持与10的固定优先级相关联(即,大于任何中缀运算符的优先级(,这一点不能改变。

为了编写一个能够正确反映构造函数优先级的Show实例,您需要编写:

instance Show a => Show (MyMaybe a) where
showsPrec _ MyNothing = showString "MyNothing"
showsPrec d (MyJust x) = showParen (d > app_prec) $
showString "MyJust " . showsPrec (app_prec+1) x
where app_prec = 10

请注意,这遵循Show类文档中给出的Leaf模板。

如果您将app_prec的值更改为其他值,那么如果您只显示MyMaybe类型或嵌套的MyMaybe类型,则情况看起来会很好,但如果您将其与其他类型组合,则会开始崩溃。例如,使用我对app_prec = 10的定义,以下内容可以正确工作:

> MyJust (Just 10)
MyJust (Just 10)

但是,如果您将其更改为不正确的app_prec = 6以匹配问题中的定义,则会产生损坏的输出:

> MyJust (Just 10)
MyJust Just 10

最新更新