1
1
{-# LANGUAGE TemplateHaskell #-}
2
2
{-# LANGUAGE TypeOperators #-}
3
+ {-# LANGUAGE FlexibleInstances #-}
3
4
--------------------------------------------------------------------------------
4
5
-- |
5
6
-- Module : Data.Comp.Multi.Derive.Show
@@ -17,13 +18,17 @@ module Data.Comp.Multi.Derive.Show
17
18
(
18
19
ShowHF (.. ),
19
20
KShow (.. ),
20
- makeShowHF
21
+ makeShowHF ,
22
+ ShowConstr (.. ),
23
+ makeShowConstr
21
24
) where
22
25
23
26
import Data.Comp.Derive.Utils
24
27
import Data.Comp.Multi.Algebra
25
28
import Data.Comp.Multi.HFunctor
26
29
import Language.Haskell.TH
30
+ import Data.Tree
31
+ import Data.Tree.View
27
32
28
33
{-| Signature printing. An instance @ShowHF f@ gives rise to an instance
29
34
@KShow (HTerm f)@. -}
@@ -36,9 +41,9 @@ class ShowHF f where
36
41
class KShow a where
37
42
kshow :: a i -> K String i
38
43
39
- showConstr :: String -> [String ] -> String
40
- showConstr con [] = con
41
- showConstr con args = " (" ++ con ++ " " ++ unwords args ++ " )"
44
+ showConstr' :: String -> [String ] -> String
45
+ showConstr' con [] = con
46
+ showConstr' con args = " (" ++ con ++ " " ++ unwords args ++ " )"
42
47
43
48
{-| Derive an instance of 'ShowHF' for a type constructor of any higher-order
44
49
kind taking at least two arguments. -}
@@ -66,5 +71,46 @@ makeShowHF fname = do
66
71
allVars = zipWith (filterFarg (getBinaryFArg fArg ty)) args varNs
67
72
shows = listE $ map mkShow allVars
68
73
conName = nameBase constr
69
- body <- [| K $ showConstr conName $ shows | ]
74
+ body <- [| K $ showConstr' conName $ shows | ]
70
75
return $ Clause [pat] (NormalB body) []
76
+
77
+ {-| Constructor printing. -}
78
+ class ShowConstr f where
79
+ showConstr :: KShow a => f a i -> String
80
+
81
+ instance KShow (K (Tree String )) where
82
+ kshow (K a) = K $ showTree a
83
+
84
+ showCon' :: String -> [String ] -> String
85
+ showCon' con args = unwords $ con : filter (not . null ) args
86
+
87
+ {-| Derive an instance of 'showConstr' for a type constructor of any first-order kind
88
+ taking at least one argument. -}
89
+ makeShowConstr :: Name -> Q [Dec ]
90
+ makeShowConstr fname = do
91
+ Just (DataInfo _cxt name args' constrs _deriving) <- abstractNewtypeQ $ reify fname
92
+ let args = init args'
93
+ fArg = VarT . tyVarBndrName $ last args
94
+ argNames = map (VarT . tyVarBndrName) (init args)
95
+ complType = foldl AppT (ConT name) argNames
96
+ preCond = map (mkClassP ''KShow . (: [] )) argNames
97
+ classType = AppT (ConT ''ShowConstr) complType
98
+ constrs' <- mapM normalConExp constrs
99
+ showConstrDecl <- funD 'showConstr (showConstrClauses fArg constrs')
100
+ return [InstanceD Nothing preCond classType [showConstrDecl]]
101
+ where showConstrClauses fArg = map (genShowConstrClause fArg)
102
+ filterFarg fArg ty@ (AppT ty' _) x = (fArg == ty', varE x)
103
+ filterFarg fArg ty@ (_) x = (fArg == ty, varE x)
104
+ mkShow :: (Bool , ExpQ ) -> ExpQ
105
+ mkShow (isFArg, var)
106
+ | isFArg = [| " " | ]
107
+ | otherwise = [| unK $ kshow $ var | ]
108
+ genShowConstrClause fArg (constr, args, ty) = do
109
+ let n = length args
110
+ varNs <- newNames n " x"
111
+ let pat = ConP constr $ map VarP varNs
112
+ allVars = zipWith (filterFarg (getBinaryFArg fArg ty)) args varNs
113
+ shows = listE $ map mkShow allVars
114
+ conName = nameBase constr
115
+ body <- [| showCon' conName $ shows | ]
116
+ return $ Clause [pat] (NormalB body) []
0 commit comments