如何为基于Maybe的newtype Property自定义正确的Show实例?
为什么需要用
showsPrec 11而不是10? 核心原因是Haskell中showsPrec的括号规则,以及函数应用的优先级特性:
函数/构造函数应用的优先级是10
所有函数(包括构造函数)的应用操作优先级都是10,且是左结合的。比如Just 5是优先级10的表达式,Property Just 5会被解析为(Property Just) 5——这显然不是你想要的,你需要的是Property (Just 5),让Just 5作为Property的单个参数。showsPrec的括号判定规则showsPrec d x生成表达式x的字符串时,会根据x的固有优先级和传入的d(当前上下文优先级)决定是否加括号:- 如果
x的固有优先级 小于d,则给x包裹括号; - 否则直接输出,不加括号。
- 如果
为什么用11?
你的参数x(比如Just 5)是一个优先级为10的构造函数应用。要让它被括号包裹,必须满足10 < d——也就是d要大于10,最小的取值就是11。- 当用
showsPrec 10 x时,10 < 10不成立,所以直接输出Just 5,导致最终结果是Property Just 5,产生歧义; - 当用
showsPrec 11 x时,10 < 11成立,所以输出(Just 5),最终得到正确的Property (Just 5)。
- 当用
完整的Show实例参考
结合你的需求,正确的Show实例应该是这样的:instance Show a => Show (Property a) where showsPrec _ (Property Nothing) = showString "NoProperty" showsPrec d (Property (Just x)) = showParen (d > 10) $ showString "Property " . showsPrec 11 x这里的
showParen (d > 10)是为了遵循Show类的规范:当Property ...处于优先级高于10的上下文时(虽然Haskell中没有这种场景),会给整个表达式加括号,保持输出的正确性。
内容的提问来源于stack exchange,提问作者Clinton
相关产品推荐
相关产品推荐

