33-- This module contains a generic show function defined using
44-- @generics-sop@.
55--
6- module Generics.SOP.Show (gshow ) where
6+ module Generics.SOP.Show (gshowsPrec , gshow ) where
77
8- import Data.List (intercalate )
8+ import Data.List (intersperse )
99
1010import Generics.SOP
1111
@@ -16,44 +16,68 @@ import Generics.SOP
1616-- 'deriving Show'.
1717--
1818-- It serves as an example of an SOP-style generic function that makes
19- -- use of metadata. However, it does currently not handle parentheses
20- -- correctly, and is therefore not really usable as a replacement.
19+ -- use of metadata.
2120--
22- -- If you want to use it anyway on a datatype @T@ for which you have
23- -- a 'Generics.SOP.Generic' instance, you can use 'gshow' as follows:
21+ -- If you want to use it on a datatype @T@ for which you have a
22+ -- 'Generics.SOP.Generic' instance, you can use 'gshowsPrec' as
23+ -- follows:
2424--
2525-- > instance Show T where
26- -- > show = gshow
26+ -- > showsPrec = gshowsPrec
2727--
28- gshow :: forall a . (Generic a , HasDatatypeInfo a , All2 Show (Code a ))
29- => a -> String
30- gshow a =
31- gshow' (constructorInfo (datatypeInfo (Proxy :: Proxy a ))) (from a)
28+ gshowsPrec :: forall a . (Generic a , HasDatatypeInfo a , All2 Show (Code a ))
29+ => Int -> a -> ShowS
30+ gshowsPrec prec a =
31+ gshowsPrec' prec (constructorInfo (datatypeInfo (Proxy :: Proxy a ))) (from a)
3232
33- gshow' :: (All2 Show xss , SListI xss ) => NP ConstructorInfo xss -> SOP I xss -> String
34- gshow' cs ( SOP sop) = hcollapse $ hcliftA2 allp goConstructor cs sop
33+ gshow :: (Generic a , HasDatatypeInfo a , All2 Show ( Code a )) => a -> String
34+ gshow a = gshowsPrec 0 a " "
3535
36- goConstructor :: All Show xs => ConstructorInfo xs -> NP I xs -> K String xs
37- goConstructor (Constructor n) args =
38- K $ intercalate " " (n : args')
36+ gshowsPrec' :: (All2 Show xss , SListI xss ) => Int -> NP ConstructorInfo xss -> SOP I xss -> ShowS
37+ gshowsPrec' prec cs (SOP sop) =
38+ hcollapse $ hcliftA2 allp (goConstructor prec) cs sop
39+
40+ goConstructor :: All Show xs => Int -> ConstructorInfo xs -> NP I xs -> K ShowS xs
41+ goConstructor prec (Constructor n) args =
42+ K $
43+ showParen
44+ (fixity <= prec)
45+ (foldr (.) id $ intersperse (showString " " ) (showString n : args'))
3946 where
40- args' :: [String ]
41- args' = hcollapse $ hcliftA p (K . show . unI) args
47+ args' :: [ShowS ]
48+ args' = hcollapse $ hcliftA p (K . showsPrec 11 . unI) args
49+
50+ -- With fixity = 11 the parens will be shown only if the enclosing
51+ -- context is a function application. This is correct because
52+ -- function application is the only thing that binds tightly
53+ -- enough to force parens around this expression.
54+ fixity = 11
4255
43- goConstructor (Record n ns) args =
44- K $ n ++ " {" ++ intercalate " , " args' ++ " }"
56+ goConstructor prec (Record n ns) args =
57+ K $
58+ showParen
59+ (fixity <= prec)
60+ (showString n . showString " {" . foldr (.) id (intersperse (showString " , " ) args') . showString " }" )
4561 where
46- args' :: [String ]
62+ args' :: [ShowS ]
4763 args' = hcollapse $ hcliftA2 p goField ns args
4864
49- goConstructor (Infix n _ _) (arg1 :* arg2 :* Nil ) =
50- K $ show arg1 ++ " " ++ show n ++ " " ++ show arg2
65+ -- With fixity = 12 the parens will never be shown. This is
66+ -- correct because record construction binds tighter than even
67+ -- function application!
68+ fixity = 12
69+
70+ goConstructor prec (Infix n _ fixity) (I arg1 :* I arg2 :* Nil ) =
71+ K $
72+ showParen
73+ (fixity <= prec)
74+ (showsPrec fixity arg1 . showString " " . showString n . showString " " . showsPrec fixity arg2)
5175#if __GLASGOW_HASKELL__ < 800
52- goConstructor (Infix _ _ _) _ = error " inaccessible"
76+ goConstructor _ (Infix _ _ _) _ = error " inaccessible"
5377#endif
5478
55- goField :: Show a => FieldInfo a -> I a -> K String a
56- goField (FieldInfo field) (I a) = K $ field ++ " = " ++ show a
79+ goField :: Show a => FieldInfo a -> I a -> K ShowS a
80+ goField (FieldInfo field) (I a) = K $ showString field . showString " = " . showsPrec 0 a
5781
5882p :: Proxy Show
5983p = Proxy
0 commit comments