Получение экземпляров с помощью TypeFamilies

У меня есть класс типа Foo с ассоциированным типом:

{-# LANGUAGE TypeFamilies #-}

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

Теперь я хочу определить тип данных, который содержит один из связанных типов, и получить экземпляр Show для него:

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

Это не скомпилируется, потому что вы не можете гарантировать, что существует экземпляр Show для Bar a

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

Я могу исправить проблему, включив FlexibleContexts и UndecidableInstances и нажимая инструкцию Show вручную следующим образом

{-# 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

Но это не особенно удовлетворительно, особенно когда Baz является более сложным, чем простая оболочка вокруг одного значения или когда я также хочу получить экземпляры других классов типов. Есть ли выход?

Ответ 1

Вы можете использовать StandaloneDeriving, чтобы просить GHC генерировать тот же самый экземпляр Show как всегда, но с другим контекстом:

{-# 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)