{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
{-# LANGUAGE ConstraintKinds, DataKinds, GADTs, TypeFamilies, TypeOperators #-}

module T9747 where
import Data.List (intercalate)
import Data.Proxy
import Data.Kind (Type, Constraint)

data HList :: [Type] -> Type where
  Nil :: HList '[]
  Cons :: a -> HList as -> HList (a ': as)

type family HListAll (c :: Type -> Constraint)
                     (ts :: [Type]) :: Constraint where
  HListAll c '[] = ()
  HListAll c (t ': ts) = (c t, HListAll c ts)

showHList :: HListAll Show ts => HList ts -> String
showHList = ("[" ++ ) . (++"]") . intercalate ", " . go
  where
    go :: HListAll Show ts => HList ts -> [String]
    go Nil = []
    go (Cons x xs) = show x : go xs

-- Things work okay up to this point
test :: String
test = showHList (Cons (2::Int)
                 (Cons (3.1 :: Float)
                 (Cons 'c' Nil)))

type family ConFun (t :: Type) :: Type -> Constraint
data Tag
type instance ConFun Tag = Group

class (Show a, Eq a, Ord a) => Group a

-- This is notionally similar to showHList
bar :: HListAll (ConFun l) ts => Proxy l -> HList ts -> ()
bar _ _ = ()

baz :: (ConFun l a, ConFun l b) => Proxy l -> HList [a,b] -> ()
baz = bar
