1
votes

I have a Haskell record data type that looks like this:

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

I can't derive a Show instance from this because of WS.Sink has no Show instance.

How can I make a Show instance that excludes just the clientSink field, but prints the rest of the record fields like a normal record?

Should I just create a custom Show instance for WS.Sink?

2
I would make a dummy Show instance for WS.Sink.augustss

2 Answers

9
votes

Add a Show instance for WS.Sink

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

or whatever dummy value you want.

6
votes

I'm not sure you really want an instance of Show, in this case. From the docs.

Derived instances of Show have the following properties, which are compatible with derived instances of Read:

  • The result of show is a syntactically correct Haskell expression containing only constants, given the fixity declarations in force at the point where the type is declared. It contains only the constructor names defined in the data type, parentheses, and spaces. When labelled constructor fields are used, braces, commas, field names, and equal signs are also used.

This does come with the caveat that it applies only to derived instances, but I'm a stickler for contracts, and have gotten used to assuming that read . show is effectively a no-op. You'd run into this same problem again when trying to automatically derive an instance for Read of course, so it's not like you would be introducing a semantic error by using Show now, it's just a matter of preference.

Depending on your context (taking a wild guess, you're trying to debug by printing intermediate values somewhere?) defining another typeclass and implementing a toString-like function might work best for you without being potentially misleading as to the show functionality of your instance. E.g.,

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)
                 ++ "}"

And then if you wanted to turn this into a Show instance it's as simple as

instance Show Client where
    show = toString