10
votes

I have a type class Foo with an associated type:

{-# LANGUAGE TypeFamilies #-}

class Foo a where
    type Bar a
    foo :: a -> Bar a

Now I want to define a data type that holds one of the associated types, and derive a Show instance for it:

data Baz a = Baz (Bar a) deriving (Show)

This doesn't compile, though, because you can't guarantee that there is a Show instance for Bar a

No instance for (Show (Bar a))
  arising from the 'deriving' clause of a data type declaration

I can fix the problem by turning on FlexibleContexts and UndecidableInstances and writing a manual Show instance as follows

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}

data Baz a = Bar a

instance (Show a, Show (Bar a)) => Show (Baz a) where
    showsPrec _ (Baz x) = showString "Baz " . shows x

But that's not particularly satisfactory, especially when Baz is a more complicated than a simple wrapper around one value, or when I also want to derive instances of other type classes. Is there a way out?

1

1 Answers

15
votes

You can use StandaloneDeriving to ask GHC to generate the same Show instance as ever, but with a different context:

{-# LANGUAGE FlexibleContexts, StandaloneDeriving, TypeFamilies, UndecidableInstances #-}

class Foo a where
    type Bar a
    foo :: a -> Bar a

data Baz a = Baz (Bar a)
deriving instance Show (Bar a) => Show (Baz a)