我正在做一个关于为我的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)
Run Code Online (Sandbox Code Playgroud)
我的代码有效,但有些事情我不明白。首先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
Run Code Online (Sandbox Code Playgroud)
如果您将 的值更改为其他值app_prec,那么如果您只显示MyMaybe类型或嵌套MyMaybe类型,事情似乎可以正常工作,但如果您将其与其他类型组合,则会开始崩溃。例如,使用我的定义 with app_prec = 10,以下内容正常工作:
> MyJust (Just 10)
MyJust (Just 10)
Run Code Online (Sandbox Code Playgroud)
但是,如果您将其更改为不正确app_prec = 6以匹配问题中的定义,则会产生损坏的输出:
> MyJust (Just 10)
MyJust Just 10
Run Code Online (Sandbox Code Playgroud)