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

时间:2012-10-05 18:28:01

标签: haskell

我有一个看起来像这样的Haskell记录数据类型:

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

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

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

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

2 个答案:

答案 0 :(得分:6)

为WS.Sink添加Show实例

instance Show WS.Sink where show a = "Sink"

或任何你想要的虚拟值。

答案 1 :(得分:6)

在这种情况下,我不确定你真的想要一个Show的实例。来自the docs

  

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