    {-# LANGUAGE UndecidableInstances #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE KindSignatures #-}
    {-# LANGUAGE PolyKinds #-}
    {-# LANGUAGE DataKinds #-}
    {-# LANGUAGE TypeOperators #-}
    {-# LANGUAGE KindSignatures #-}

    -------------------------------------------------------------------------------
    ---- |
    ---- Module      :  Data.Generics.Internal.Errors
    ---- Copyright   :  (C) 2020 Csongor Kiss
    ---- License     :  BSD3
    ---- Maintainer  :  Csongor Kiss <kiss.csongor.kiss@gmail.com>
    ---- Stability   :  experimental
    ---- Portability :  non-portable
    ----
    ---- Provide more legible type errors as described in
    ---- (https://kcsongor.github.io/report-stuck-families/)[this blog post].
    -------------------------------------------------------------------------------

    module Data.Generics.Internal.Errors
     ( NoGeneric
     , Defined
     , Defined_list

     , QuoteType
     , PrettyError
     ) where

    import GHC.Generics
    import GHC.TypeLits
    import Data.Kind

    type family NoGeneric (a :: Type) (ctxt :: [ErrorMessage]) :: Constraint where
      NoGeneric a ctxt = PrettyError ('Text "No instance for " ':<>: QuoteType (Generic a)
                                       ': ctxt)
    type family PrettyError (ctxt :: [ErrorMessage]) :: k where
      PrettyError '[] = TypeError ('Text "")
      PrettyError (c ': cs) = TypeError ('Text "| " ':<>: c ':$$: PrettyLines cs)

    type family PrettyLines (ctxt :: [ErrorMessage]) :: ErrorMessage where
      PrettyLines '[] = 'Text ""
      PrettyLines (c ': cs) = 'Text "|   " ':<>: c ':$$: PrettyLines cs

    type family Defined (break :: Type -> Type) (err :: Constraint) (a :: k) :: k where
      Defined Void1 _ _ = Any
      Defined _ _     k = k

    type family Defined_list (break :: [*]) (err :: Constraint) (a :: k) :: k where
      Defined_list '[Void] _ _ = Any
      Defined_list _ _        k = k

    data Void1 a
    data Void
    type family Any :: k

    type family QuoteType (typ :: k) :: ErrorMessage where
      QuoteType typ = 'Text "‘" ':<>: 'ShowType typ ':<>: 'Text "’"