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

dan*_*dan 1 haskell

我有一个Haskell记录数据类型,如下所示:

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

我无法从中导出Show实例,因为WS.Sink没有Show实例.

如何创建一个仅排除clientSink字段的Show实例,而是打印其他记录字段,如普通记录?

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

小智 7

为WS.Sink添加Show实例

instance Show WS.Sink where show a = "Sink"
Run Code Online (Sandbox Code Playgroud)

或者你想要的虚拟价值.


小智 6

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)
                 ++ "}"
Run Code Online (Sandbox Code Playgroud)

然后如果你想把它变成一个Show实例就像它一样简单

instance Show Client where
    show = toString
Run Code Online (Sandbox Code Playgroud)