Ghc-7.6 class instances for dependent types

Inhomogeneous lists are one example given for a new ghc 7.6 dependent object type:

data HList :: [*] -> * where HNil :: HList '[] HCons:: a -> HList t -> HList (a ': t) 

The list of li examples compiles fine:

 li = HCons "Int: " (HCons 234 (HCons "Integer: " (HCons 129877645 HNil))) 

Obviously, we would like the HList to be in the Show class, but I can only create an instance of the working class that uses mutually recursive constraints (superclasses):

 instance Show (HList '[]) where show HNil = "[]" instance (Show a, Show' (HList t)) => Show (HList (a ': t)) where show l = "[" ++ show' l ++ "]" class Show' a where show' :: a -> String instance Show' (HList '[]) where show' HNil = "" instance (Show a, Show' (HList t)) => Show' (HList (a ': t)) where show' (HCons hl) = case l of HNil -> show h HCons _ _ -> show h ++ ", " ++ (show' l) 

The code compiles fine, and li displays correctly. The necessary compilation flags are:

 {-# LANGUAGE DataKinds, TypeOperators, KindSignatures, FlexibleContexts, GADTs, FlexibleInstances #-} 

I tried many variations of the following much more direct definition, but it does not compile if I cannot understand the ghc error messages:

 instance Show (HList '[]) where show HNil = "[]" instance (Show a, Show (HList t)) => Show (HList (a ': t)) where show l = "[" ++ (show' l) ++ "]" where show' (HCons hs) = case s of HNil -> show h HCons _ _ -> show h ++ ", " ++ (show' s) 

Some Haskell / ghc experts may understand why this may not work, and I would be happy to hear the reason.

thanks

Hans Peter


Thank you, Hammar, for your two nice working examples, having improved in my first example.

But I still do not understand why my second example does not work. You say that "... show" knows how to show the current item type, not the rest. "But will this comment not be applied in the following (working) code:

 instance Show (HList '[]) where show HNil = "" instance (Show a, Show (HList t)) => Show (HList (a ': t)) where show (HCons ht) = case t of HNil -> show h HCons _ _ -> show h ++ ", " ++ (show t) 
+7
source share
2 answers

As Nathan said in the comments, show' knows how to show the current item type, not the rest.

As in the first example, we can get around this by creating a new type class for show' , although you can get away with only one instance of Show :

 -- Specializing show' to HLists avoids needing a Show' (HList ts) constraint -- here, which would require UndecidableInstances. instance (Show' ts) => Show (HList ts) where show xs = "[" ++ show' xs ++ "]" class Show' ts where show' :: HList ts -> String instance Show' '[] where show' HNil = "" instance (Show a, Show' ts) => Show' (a ': ts) where show' (HCons as) = case s of HNil -> show a HCons {} -> show a ++ ", " ++ show' s 

Another hacker way to get all the Show show' necessary restrictions in show' is to use ConstraintKinds to directly create a list of all the necessary restrictions.

 -- In addition to the extensions in the original code: {-# LANGUAGE TypeFamilies, ConstraintKinds, UndecidableInstances #-} import GHC.Exts -- ShowTypes [a, b, c, ...] = (Show a, Show b, Show c, ...) type family ShowTypes (a :: [*]) :: Constraint type instance ShowTypes '[] = () type instance ShowTypes (a ': t) = (Show a, ShowTypes t) instance ShowTypes ts => Show (HList ts) where show xs = "[" ++ show' xs ++ "]" where show' :: ShowTypes ts => HList ts -> String show' HNil = "" show' (HCons hs) = case s of HNil -> show h HCons {} -> show h ++ ", " ++ show' s 
+5
source

Thanks to the second hammar solution, I can offer an even more general approach that works for the general class (but I suppose he meant it):

 type family ConstrainedTypes (a :: [*]) (f :: * -> Constraint) :: Constraint type instance ConstrainedTypes '[] b = () type instance ConstrainedTypes (a ': t) b = (ba, ConstrainedTypes tb) instance ConstrainedTypes ts Show => Show (HList ts) where show xs = "[" ++ show' xs ++ "]" where show' :: ConstrainedTypes ts Show => HList ts -> String show' HNil = "" show' (HCons hs) = case s of HNil -> show h HCons {} -> show h ++ ", " ++ show' s 

Thanks again for the great help.

+2
source

All Articles