I have a class identical to Show , and I would like to make an instance of this class for each type of tuple. This is usually done by separately writing instances for each type of tuple.
instance (Show a, Show b) => Show (a,b) where showsPrec _ (a,b) s = show_tuple [shows a, shows b] s instance (Show a, Show b, Show c) => Show (a, b, c) where showsPrec _ (a,b,c) s = show_tuple [shows a, shows b, shows c] s instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where showsPrec _ (a,b,c,d) s = show_tuple [shows a, shows b, shows c, shows d] s ...
Writing one instance to one type of tuple leads to a large number of patterns and it is easy to see a common pattern common to all showPrec implementations. To avoid this kind of patterns, I thought that I could use Data.Generics from Scrap your pattern and implement tuple folding, for example
showTuple = intercalate " " . gmapQ ("" `mkQ` show)
But showTuple not working for any reason
> showTuple (1,2) " "
I think the problem is that show is polymorphic, because if I specialize in showTuple , then it works
showTupleInt = intercalate " " . gmapQ ("" `mkQ` (show :: Int -> String))
> showTupleInt (1::Int,2::Int) "1 2"
I checked the gshow code that does something similar to what I need, but I cannot figure out how this works. If I try to import its code into GHCI, I get an error message:
> let gshows = (\t -> showChar '(' . (showString . showConstr . toConstr $ t) . (foldr (.) id . gmapQ ((showChar ' ' .) . gshows) $ t) . showChar ')' ) `extQ` (shows :: String -> ShowS) <interactive>:262:59: Could not deduce (a ~ d) from the context (Data a) bound by the inferred type of gshows :: Data a => a -> String -> String at <interactive>:(259,5)-(264,44) or from (Data d) bound by a type expected by the context: Data d => d -> String -> String at <interactive>:262:33-65 `a' is a rigid type variable bound by the inferred type of gshows :: Data a => a -> String -> String at <interactive>:259:5 `d' is a rigid type variable bound by a type expected by the context: Data d => d -> String -> String at <interactive>:262:33 Expected type: d -> String -> String Actual type: a -> String -> String In the second argument of `(.)', namely `gshows' In the first argument of `gmapQ', namely `((showChar ' ' .) . gshows)' In the second argument of `(.)', namely `gmapQ ((showChar ' ' .) . gshows)'
I have two questions:
- what's wrong with
showTuple and how can I fix it so that it works with tuples of any size - How does
gshow work and why, if I import its code into GHCI, do I get this error?
EDIT: I am studying Data.Generics and generally SYM, so I would like to use this module. I will accept the answer only if it uses only this module. Thanks.