如何为Haskell记录自定义Show实例?

3

我有一个Haskell记录数据类型,长得像这样:

data Client = Client { clientId :: Int
                     , nickname :: Text
                     , clientSink :: Maybe (WS.Sink WS.Hybi00)
                     , clientRoom :: Maybe Room
                     }

由于WS.Sink没有Show实例,因此我无法从中推导出Show实例。

我该如何创建一个Show实例,仅排除clientSink字段,但像普通记录一样打印其余记录字段?

我应该为WS.Sink创建自定义Show实例吗?


我会为 WS.Sink 创建一个虚拟的 Show 实例。 - augustss
2个回答

11
为 WS.Sink 添加一个 Show 实例。
instance Show WS.Sink where show a = "Sink"

或任何你想要的虚拟值。


7
我不确定在这种情况下您真的想要一个Show实例。请参阅文档

派生的Show实例具有以下属性,与Read的派生实例兼容:

  • show的结果是一个符合语法规则的Haskell表达式,仅包含常量,给定类型声明点处生效的固定声明。它仅包含数据类型中定义的构造函数名称、括号和空格。当使用标记的构造函数字段时,还使用大括号、逗号、字段名称和等号。

需要注意的是,这仅适用于派生实例,但我对契约非常严格,并已习惯于假设read . show实际上是无操作的。当然,当尝试自动推导Read实例时,您将再次遇到同样的问题,因此使用Show现在并不会引入语义错误,只是一种偏好。

根据您的上下文(猜测您正在尝试通过在某个地方打印中间值来调试?),定义另一个类型类并实现类似于toString的函数可能是最适合您的选择,而不会对您的实例的show功能产生潜在误导。例如:

class ToString a where
    toString :: a -> String

instance ToString Client where
    toString c = "Client {"
                 ++ shows (clientId c) ", "
                 ++ shows (nickname c) ", "
                 ++ shows (isJust (clientSink c)) ", "
                 ++ show (clientRoom c)
                 ++ "}"

然后,如果你想将这个转换成一个Show实例,只需要简单地执行以下操作:

instance Show Client where
    show = toString

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接