diff --git a/Language/Haskell/Tools/AST/Gen/Binds.hs b/Language/Haskell/Tools/AST/Gen/Binds.hs
--- a/Language/Haskell/Tools/AST/Gen/Binds.hs
+++ b/Language/Haskell/Tools/AST/Gen/Binds.hs
@@ -28,7 +28,7 @@
 
 -- | Creates a function binding (@ f 0 = 1; f x = x @). All matches must have the same name.
 mkFunctionBind :: [Match dom] -> ValueBind dom
-mkFunctionBind = mkAnn child . UFunBind . mkAnnList indentedList
+mkFunctionBind = mkAnn child . UFunBind . mkAnnList (indented list)
 
 -- | A simplified function for creating function bindings without local definitions or guards.
 mkFunctionBind' :: Name dom -> [([Pattern dom], Expr dom)] -> ValueBind dom
@@ -38,24 +38,25 @@
 mkMatch :: MatchLhs dom -> Rhs dom -> Maybe (LocalBinds dom) -> Match dom
 mkMatch lhs rhs locs 
   = mkAnn (child <> child <> child) 
-      $ UMatch lhs rhs (mkAnnMaybe (optBefore " ") locs)
+      $ UMatch lhs rhs (mkAnnMaybe (after " " opt) locs)
 
 -- | Creates a match lhs with the function name and parameter names (@ f a b @)
 mkMatchLhs :: Name dom -> [Pattern dom] -> MatchLhs dom
-mkMatchLhs n pats = mkAnn (child <> child) $ UNormalLhs n (mkAnnList (listSepBefore " " " ") pats)
+mkMatchLhs n pats = mkAnn (child <> child) $ UNormalLhs n (mkAnnList (after " " $ separatedBy " " list) pats)
 
 -- | Creates an infix match lhs for an operator (@ a + b @)
 mkInfixLhs :: Pattern dom -> Operator dom -> Pattern dom -> [Pattern dom] -> MatchLhs dom
-mkInfixLhs lhs op rhs pats = mkAnn (child <> child <> child <> child) $ UInfixLhs lhs op rhs (mkAnnList (listSepBefore " " " ") pats)
+mkInfixLhs lhs op rhs pats 
+  = mkAnn (child <> child <> child <> child) $ UInfixLhs lhs op rhs (mkAnnList (after " " $ separatedBy " " list) pats)
 
 -- | Local bindings attached to a declaration (@ where x = 42 @)
-mkLocalBinds :: Int -> [LocalBind dom] -> MaybeLocalBinds dom
+mkLocalBinds :: [LocalBind dom] -> MaybeLocalBinds dom
 -- TODO: make the indentation automatic
-mkLocalBinds col = mkAnnMaybe (optBefore ("\n" ++ replicate (col - 1) ' ' ++ "where ")) 
-                     . Just . mkAnn child . ULocalBinds . mkAnnList indentedList
+mkLocalBinds = mkAnnMaybe (relativeIndented 2 $ after "\nwhere " opt)
+                     . Just . mkAnn child . ULocalBinds . mkAnnList (indented list)
 
 mkLocalBinds' :: [LocalBind dom] -> LocalBinds dom
-mkLocalBinds' = mkAnn (" where " <> child) . ULocalBinds . mkAnnList indentedList
+mkLocalBinds' = mkAnn (" where " <> child) . ULocalBinds . mkAnnList (indented list)
 
 -- | Creates a local binding for a value
 mkLocalValBind :: ValueBind dom -> LocalBind dom
@@ -71,22 +72,22 @@
 
 -- | Creates a type signature (@ f :: Int -> Int @)
 mkTypeSignature :: Name dom -> Type dom -> TypeSignature dom
-mkTypeSignature n t = mkAnn (child <> " :: " <> child) (UTypeSignature (mkAnnList (listSep ", ") [n]) t)
+mkTypeSignature n t = mkAnn (child <> " :: " <> child) (UTypeSignature (mkAnnList (separatedBy ", " list) [n]) t)
 
 -- | Creates a left-associative fixity declaration (@ infixl 5 +, - @).
 mkInfixL :: Int -> Operator dom -> FixitySignature dom
 mkInfixL prec op = mkAnn (child <> " " <> child <> " " <> child) 
-                     $ UFixitySignature (mkAnn "infixl" AssocLeft) (mkAnn (fromString (show prec)) (Precedence prec)) (mkAnnList (listSep ", ") [op])
+                     $ UFixitySignature (mkAnn "infixl" AssocLeft) (mkAnn (fromString (show prec)) (Precedence prec)) (mkAnnList (separatedBy ", " list) [op])
 
 -- | Creates a right-associative fixity declaration (@ infixr 5 +, - @).
 mkInfixR :: Int -> Operator dom -> FixitySignature dom
 mkInfixR prec op = mkAnn (child <> " " <> child <> " " <> child) 
-                     $ UFixitySignature (mkAnn "infixr" AssocRight) (mkAnn (fromString (show prec)) (Precedence prec)) (mkAnnList (listSep ", ") [op])
+                     $ UFixitySignature (mkAnn "infixr" AssocRight) (mkAnn (fromString (show prec)) (Precedence prec)) (mkAnnList (separatedBy ", " list) [op])
 
 -- | Creates a non-associative fixity declaration (@ infix 5 +, - @).
 mkInfix :: Int -> Operator dom -> FixitySignature dom
 mkInfix prec op = mkAnn (child <> " " <> child <> " " <> child) 
-                    $ UFixitySignature (mkAnn "infix" AssocNone) (mkAnn (fromString (show prec)) (Precedence prec)) (mkAnnList (listSep ", ") [op])
+                    $ UFixitySignature (mkAnn "infix" AssocNone) (mkAnn (fromString (show prec)) (Precedence prec)) (mkAnnList (separatedBy ", " list) [op])
 
 -- | Creates an unguarded right-hand-side (@ = 3 @)
 mkUnguardedRhs :: Expr dom -> Rhs dom
@@ -94,11 +95,11 @@
 
 -- | Creates an unguarded right-hand-side (@ | x == 1 = 3; | otherwise = 4 @)
 mkGuardedRhss :: [GuardedRhs dom] -> Rhs dom
-mkGuardedRhss = mkAnn child . UGuardedRhss . mkAnnList indentedList
+mkGuardedRhss = mkAnn child . UGuardedRhss . mkAnnList (indented list)
 
 -- | Creates a guarded right-hand side of a value binding (@ | x > 3 = 2 @)    
 mkGuardedRhs :: [RhsGuard dom] -> Expr dom -> GuardedRhs dom
-mkGuardedRhs guards expr = mkAnn ("| " <> child <> " = " <> child) $ UGuardedRhs (mkAnnList (listSep ", ") guards) expr
+mkGuardedRhs guards expr = mkAnn ("| " <> child <> " = " <> child) $ UGuardedRhs (mkAnnList (separatedBy ", " list) guards) expr
 
 -- | Creates a bind statement in a pattern guard (@ Just v <- x @)
 mkGuardBind :: Pattern dom -> Expr dom -> RhsGuard dom
@@ -106,7 +107,7 @@
 
 -- | Creates a let statement in a pattern guard (@ let x = 3 @)
 mkGuardLet :: [LocalBind dom] -> RhsGuard dom
-mkGuardLet = mkAnn ("let " <> child) . UGuardLet . mkAnnList indentedList
+mkGuardLet = mkAnn ("let " <> child) . UGuardLet . mkAnnList (indented list)
 
 -- | Creates an expression to check for a pattern guard
 mkGuardCheck :: Expr dom -> RhsGuard dom
diff --git a/Language/Haskell/Tools/AST/Gen/Decls.hs b/Language/Haskell/Tools/AST/Gen/Decls.hs
--- a/Language/Haskell/Tools/AST/Gen/Decls.hs
+++ b/Language/Haskell/Tools/AST/Gen/Decls.hs
@@ -24,7 +24,7 @@
 -- | Creates a standalone deriving declaration (@ deriving instance X T @)
 mkStandaloneDeriving :: Maybe (OverlapPragma dom) -> InstanceRule dom -> Decl dom
 mkStandaloneDeriving overlap instRule = mkAnn ("deriving instance" <> child <> child) 
-                                          $ UDerivDecl (mkAnnMaybe (optBefore " ") overlap) instRule
+                                          $ UDerivDecl (mkAnnMaybe (after " " opt) overlap) instRule
 
 -- | Creates a fixity declaration (@ infixl 5 +, - @)
 mkFixityDecl :: FixitySignature dom -> Decl dom
@@ -32,7 +32,7 @@
 
 -- | Creates default types (@ default (T1, T2) @)
 mkDefaultDecl :: [Type dom] -> Decl dom
-mkDefaultDecl = mkAnn ("default (" <> child <> ")") . UDefaultDecl . mkAnnList (listSep ", ")
+mkDefaultDecl = mkAnn ("default (" <> child <> ")") . UDefaultDecl . mkAnnList (separatedBy ", " list)
 
 -- | Creates type signature declaration (@ f :: Int -> Int @)
 mkTypeSigDecl :: TypeSignature dom -> Decl dom
@@ -52,34 +52,38 @@
 mkDataDecl :: DataOrNewtypeKeyword dom -> Maybe (Context dom) -> DeclHead dom -> [ConDecl dom] -> Maybe (Deriving dom) -> Decl dom
 mkDataDecl keyw ctx dh cons derivs 
   = mkAnn (child <> " " <> child <> child <> child <> child) 
-      $ UDataDecl keyw (mkAnnMaybe (optBefore " ") ctx) dh 
-                 (mkAnnList (listSepBefore " | " " = ") cons) (mkAnnMaybe (optBefore " deriving ") derivs)
+      $ UDataDecl keyw (mkAnnMaybe (after " " opt) ctx) dh 
+                 (mkAnnList (after " = " $ separatedBy " | " list) cons) (mkAnnMaybe (after " deriving " opt) derivs)
 
 -- | Creates a GADT-style data or newtype declaration.
 mkGADTDataDecl :: DataOrNewtypeKeyword dom -> Maybe (Context dom) -> DeclHead dom -> Maybe (KindConstraint dom)
                     -> [GadtConDecl dom] -> Maybe (Deriving dom) -> Decl dom
 mkGADTDataDecl keyw ctx dh kind cons derivs 
   = mkAnn (child <> " " <> child <> child <> child <> child <> child) 
-      $ UGDataDecl keyw (mkAnnMaybe (optBefore " ") ctx) dh 
-                  (mkAnnMaybe (optBefore " ") kind) (mkAnnList (listSepBefore " | " " = ") cons) (mkAnnMaybe (optBefore " deriving ") derivs)
+      $ UGDataDecl keyw (mkAnnMaybe (after " " opt) ctx) dh 
+                  (mkAnnMaybe (after " " opt) kind) (mkAnnList (after " = " $ separatedBy " | " list) cons) 
+                  (mkAnnMaybe (after " deriving " opt) derivs)
 
 -- | Creates a GADT constructor declaration (@ D1 :: Int -> T String @)
 mkGadtConDecl :: [Name dom] -> Type dom -> GadtConDecl dom
-mkGadtConDecl names typ = mkAnn (child <> " :: " <> child) $ UGadtConDecl (mkAnnList (listSep ", ") names) (mkAnn child $ UGadtNormalType typ)
+mkGadtConDecl names typ = mkAnn (child <> " :: " <> child) $ UGadtConDecl (mkAnnList (separatedBy ", " list) names) 
+                                                               (mkAnn child $ UGadtNormalType typ)
 
 -- | Creates a GADT constructor declaration with record syntax (@ D1 :: { val :: Int } -> T String @)
 mkGadtRecordConDecl :: [Name dom] -> [FieldDecl dom] -> Type dom -> GadtConDecl dom
 mkGadtRecordConDecl names flds typ 
-  = mkAnn (child <> " :: " <> child) $ UGadtConDecl (mkAnnList (listSep ", ") names) 
-      $ mkAnn (child <> " -> " <> child) $ UGadtRecordType (mkAnnList (listSepBeforeAfter ", " "{ " " }") flds) typ
+  = mkAnn (child <> " :: " <> child) $ UGadtConDecl (mkAnnList (separatedBy ", " list) names) 
+      $ mkAnn (child <> " -> " <> child) 
+      $ UGadtRecordType (mkAnnList (after "{ " $ separatedBy ", " $ followedBy " }" list) flds) typ
 
 -- | Creates an ordinary data constructor (@ C t1 t2 @)
 mkConDecl :: Name dom -> [Type dom] -> ConDecl dom
-mkConDecl name args = mkAnn (child <> child) $ UConDecl name (mkAnnList (listSepBefore " " " ") args)
+mkConDecl name args = mkAnn (child <> child) $ UConDecl name (mkAnnList (after " " $ separatedBy " " $ list) args)
 
 -- | Creates a record data constructor (@ Point { x :: Double, y :: Double } @)
 mkRecordConDecl :: Name dom -> [FieldDecl dom] -> ConDecl dom
-mkRecordConDecl name fields = mkAnn (child <> " { " <> child <> " }") $ URecordDecl name (mkAnnList (listSep ", ") fields)
+mkRecordConDecl name fields 
+  = mkAnn (child <> " { " <> child <> " }") $ URecordDecl name (mkAnnList (separatedBy ", " list) fields)
 
 -- | Creates an infix data constructor (@ t1 :+: t2 @)
 mkInfixConDecl :: Type dom -> Operator dom -> Type dom -> ConDecl dom
@@ -87,12 +91,12 @@
 
 -- | Creates a field declaration (@ fld :: Int @) for a constructor
 mkFieldDecl :: [Name dom] -> Type dom -> FieldDecl dom
-mkFieldDecl names typ = mkAnn (child <> " :: " <> child) $ UFieldDecl (mkAnnList (listSep ", ") names) typ
+mkFieldDecl names typ = mkAnn (child <> " :: " <> child) $ UFieldDecl (mkAnnList (separatedBy ", " list) names) typ
 
 -- | Creates a deriving clause following a data type declaration. (@ deriving Show @ or @ deriving (Show, Eq) @)
 mkDeriving :: [InstanceHead dom] -> Deriving dom
 mkDeriving [deriv] = mkAnn child $ UDerivingOne deriv
-mkDeriving derivs = mkAnn ("(" <> child <> ")") $ UDerivings (mkAnnList (listSep ", ") derivs)
+mkDeriving derivs = mkAnn ("(" <> child <> ")") $ UDerivings (mkAnnList (separatedBy ", " list) derivs)
 
 -- | The @data@ keyword in a type definition
 mkDataKeyword :: DataOrNewtypeKeyword dom
@@ -108,13 +112,13 @@
 mkClassDecl :: Maybe (Context dom) -> DeclHead dom -> [FunDep dom] -> Maybe (ClassBody dom) -> Decl dom
 mkClassDecl ctx dh funDeps body 
   = let fdeps = case funDeps of [] -> Nothing
-                                _ -> Just $ mkAnn child $ UFunDeps $ mkAnnList (listSep ", ") funDeps
+                                _ -> Just $ mkAnn child $ UFunDeps $ mkAnnList (separatedBy ", " list) funDeps
      in mkAnn ("class " <> child <> child <> child <> child) 
-          $ UClassDecl (mkAnnMaybe (optAfter " ") ctx) dh (mkAnnMaybe (optBefore " | ") fdeps) (mkAnnMaybe opt body) 
+          $ UClassDecl (mkAnnMaybe (followedBy " " opt) ctx) dh (mkAnnMaybe (after " | " opt) fdeps) (mkAnnMaybe opt body) 
 
 -- | Creates the list of declarations that can appear in a typeclass
 mkClassBody :: [ClassElement dom] -> ClassBody dom
-mkClassBody = mkAnn (" where " <> child) . UClassBody . mkAnnList indentedList
+mkClassBody = mkAnn (" where " <> child) . UClassBody . mkAnnList (indented list)
 
 -- | Creates a type signature as class element: @ f :: A -> B @
 mkClassElemSig :: TypeSignature dom -> ClassElement dom
@@ -143,7 +147,7 @@
 -- | Creates a functional dependency, given on the form @l1 ... ln -> r1 ... rn@
 mkFunDep :: [Name dom] -> [Name dom] -> FunDep dom
 mkFunDep lhss rhss = mkAnn (child <> " -> " <> child) 
-                       $ UFunDep (mkAnnList (listSep ", ") lhss) (mkAnnList (listSep ", ") rhss)
+                       $ UFunDep (mkAnnList (separatedBy ", " list) lhss) (mkAnnList (separatedBy ", " list) rhss)
 
 -- | Minimal pragma: @ {-\# MINIMAL (==) | (/=) \#-} @ in a class
 mkClsMinimal :: MinimalFormula dom -> ClassElement dom
@@ -157,11 +161,11 @@
 
 -- | One of the minimal formulas are needed (@ min1 | min2 @)
 mkMinimalOr :: [MinimalFormula dom] -> MinimalFormula dom
-mkMinimalOr = mkAnn child . UMinimalOr . mkAnnList (listSep " | ")
+mkMinimalOr = mkAnn child . UMinimalOr . mkAnnList (separatedBy " | " list)
 
 -- | Both of the minimal formulas are needed (@ min1 , min2 @)
 mkMinimalAnd :: [MinimalFormula dom] -> MinimalFormula dom
-mkMinimalAnd = mkAnn child . UMinimalAnd . mkAnnList (listSep ", ")
+mkMinimalAnd = mkAnn child . UMinimalAnd . mkAnnList (separatedBy ", " list)
 
 -- * Declaration heads
 
@@ -186,12 +190,12 @@
 -- | Creates a type class instance declaration (@ instance X T [where f = ...] @)
 mkInstanceDecl :: Maybe (OverlapPragma dom) -> InstanceRule dom -> Maybe (InstBody dom) -> Decl dom
 mkInstanceDecl overlap instRule body = mkAnn ("instance " <> child <> child <> child) 
-                                 $ UInstDecl (mkAnnMaybe (optBefore " ") overlap) instRule (mkAnnMaybe opt body)
+                                 $ UInstDecl (mkAnnMaybe (after " " opt) overlap) instRule (mkAnnMaybe opt body)
 
 -- | The instance declaration rule, which is, roughly, the part of the instance declaration before the where keyword.
 mkInstanceRule :: Maybe (Context dom) -> InstanceHead dom -> InstanceRule dom
 mkInstanceRule ctx ih 
-  = mkAnn (child <> child <> child) $ UInstanceRule (mkAnnMaybe (optBefore " ") Nothing) (mkAnnMaybe (optBefore " ") ctx) ih
+  = mkAnn (child <> child <> child) $ UInstanceRule (mkAnnMaybe (after " " opt) Nothing) (mkAnnMaybe (after " " opt) ctx) ih
 
 -- | Type or class name as a part of the instance declaration
 mkInstanceHead :: Name dom -> InstanceHead dom
@@ -211,7 +215,7 @@
 
 -- | Instance body is the implementation of the class functions (@ where a x = 1; b x = 2 @)
 mkInstanceBody :: [InstBodyDecl dom] -> InstBody dom
-mkInstanceBody = mkAnn (" where " <> child) . UInstBody . mkAnnList indentedList
+mkInstanceBody = mkAnn (" where " <> child) . UInstBody . mkAnnList (indented list)
 
 -- | A normal declaration (@ f x = 12 @) in a type class instance
 mkInstanceBind :: ValueBind dom -> InstBodyDecl dom
@@ -229,15 +233,16 @@
 mkInstanceDataFamilyDef :: DataOrNewtypeKeyword dom -> InstanceRule dom -> [ConDecl dom] -> Maybe (Deriving dom) -> InstBodyDecl dom
 mkInstanceDataFamilyDef keyw instRule cons derivs 
   = mkAnn (child <> " " <> child <> child <> child) 
-      $ UInstBodyDataDecl keyw instRule (mkAnnList (listSepBefore " | " " = ") cons) (mkAnnMaybe (optBefore " deriving ") derivs)
+      $ UInstBodyDataDecl keyw instRule (mkAnnList (after " = " $ separatedBy " | " list) cons) 
+                                        (mkAnnMaybe (after " deriving " opt) derivs)
 
 -- | An associated data type implemented using GADT style int a type class instance
 mkInstanceDataFamilyGADTDef :: DataOrNewtypeKeyword dom -> InstanceRule dom -> Maybe (KindConstraint dom) -> [GadtConDecl dom] 
                                  -> Maybe (Deriving dom) -> InstBodyDecl dom
 mkInstanceDataFamilyGADTDef keyw instRule kind cons derivs 
   = mkAnn (child <> " " <> child <> child <> child) 
-      $ UInstBodyGadtDataDecl mkDataKeyword instRule (mkAnnMaybe opt kind) (mkAnnList (listSepBefore " | " " = ") cons) 
-                             (mkAnnMaybe (optBefore " deriving ") derivs)
+      $ UInstBodyGadtDataDecl mkDataKeyword instRule (mkAnnMaybe opt kind) (mkAnnList (after " = " $ separatedBy " | " list) cons) 
+                             (mkAnnMaybe (after " deriving " opt) derivs)
 
 -- | Specialize instance pragma (no phase selection is allowed) in a type class instance
 mkInstanceSpecializePragma :: Type dom -> InstBodyDecl dom
@@ -271,7 +276,8 @@
 
 -- | Creates a role annotations (@ type role Ptr representational @)
 mkRoleDecl :: QualifiedName dom -> [Role dom] -> Decl dom
-mkRoleDecl name roles = mkAnn ("type role " <> child <> child) $ URoleDecl name $ mkAnnList (listSepBefore " " " ") roles
+mkRoleDecl name roles 
+  = mkAnn ("type role " <> child <> child) $ URoleDecl name $ mkAnnList (separatedBy " " $ after " " list) roles
 
 -- | Marks a given type parameter as @nominal@.
 mkNominalRole :: Role dom
@@ -290,7 +296,7 @@
 -- | Creates a foreign import (@ foreign import foo :: Int -> IO Int @)
 mkForeignImport :: CallConv dom -> Maybe (Safety dom) -> Name dom -> Type dom -> Decl dom
 mkForeignImport cc safety name typ = mkAnn (child <> child <> " " <> child <> " :: " <> child) 
-                                       $ UForeignImport cc (mkAnnMaybe (optBefore " ") safety) name typ
+                                       $ UForeignImport cc (mkAnnMaybe (after " " opt) safety) name typ
 
 -- | Creates a foreign export (@ foreign export ccall foo :: Int -> IO Int @)
 mkForeignExport :: CallConv dom -> Name dom -> Type dom -> Decl dom
@@ -316,16 +322,16 @@
 
 -- | Creates a type family declaration ( @type family F x@ )
 mkTypeFamily :: DeclHead dom -> Maybe (TypeFamilySpec dom) -> Decl dom
-mkTypeFamily dh famSpec = mkAnn child $ UTypeFamilyDecl (mkAnn (child <> child) $ UTypeFamily dh (mkAnnMaybe (optBefore " ") famSpec))
+mkTypeFamily dh famSpec = mkAnn child $ UTypeFamilyDecl (mkAnn (child <> child) $ UTypeFamily dh (mkAnnMaybe (after " " opt) famSpec))
 
 -- | Creates a closed type family declaration ( @type family F x where F Int = (); F a = Int@ )
 mkClosedTypeFamily :: DeclHead dom -> Maybe (KindConstraint dom) -> [TypeEqn dom] -> Decl dom
 mkClosedTypeFamily dh kind typeqs = mkAnn (child <> child <> " where " <> child) 
-                                      $ UClosedTypeFamilyDecl dh (mkAnnMaybe (optBefore " ") kind) (mkAnnList indentedList typeqs)
+                                      $ UClosedTypeFamilyDecl dh (mkAnnMaybe (after " " opt) kind) (mkAnnList (indented list) typeqs)
 
 -- | Creates a data family declaration (@ data family A a :: * -> * @)   
 mkDataFamily :: DeclHead dom -> Maybe (KindConstraint dom) -> Decl dom
-mkDataFamily dh kind = mkAnn child $ UTypeFamilyDecl (mkAnn (child <> child) $ UDataFamily dh (mkAnnMaybe (optBefore " ") kind))
+mkDataFamily dh kind = mkAnn child $ UTypeFamilyDecl (mkAnn (child <> child) $ UDataFamily dh (mkAnnMaybe (after " " opt) kind))
 
 -- | Specifies the kind of a type family (@ :: * -> * @)
 mkTypeFamilyKindSpec :: KindConstraint dom -> TypeFamilySpec dom
@@ -334,7 +340,7 @@
 -- | Specifies the injectivity of a type family (@ = r | r -> a @)
 mkTypeFamilyInjectivitySpec :: Name dom -> [Name dom] -> TypeFamilySpec dom
 mkTypeFamilyInjectivitySpec res dependent 
-  = mkAnn child (UTypeFamilyInjectivity $ mkAnn (child <> " -> " <> child) $ UInjectivityAnn res (mkAnnList (listSep " ") dependent))
+  = mkAnn child (UTypeFamilyInjectivity $ mkAnn (child <> " -> " <> child) $ UInjectivityAnn res (mkAnnList (separatedBy " " list) dependent))
 
 -- | Type equations as found in closed type families (@ T A = S @)
 mkTypeEqn :: Type dom -> Type dom -> TypeEqn dom
@@ -348,23 +354,25 @@
 mkDataInstance :: DataOrNewtypeKeyword dom -> InstanceRule dom -> [ConDecl dom] -> Maybe (Deriving dom) -> Decl dom
 mkDataInstance keyw instRule cons derivs 
   = mkAnn (child <> " instance " <> child <> " = " <> child <> child) 
-      $ UDataInstDecl keyw instRule (mkAnnList (listSepBefore " | " " = ") cons) (mkAnnMaybe (optBefore " deriving ") derivs)
+      $ UDataInstDecl keyw instRule (mkAnnList (after " = " $ separatedBy " | " list) cons) 
+                                    (mkAnnMaybe (after " deriving " opt) derivs)
 
 -- | Creates a GADT-style data instance declaration (@ data instance Fam T where ... @)
 mkGadtDataInstance :: DataOrNewtypeKeyword dom -> InstanceRule dom -> Maybe (KindConstraint dom) -> [GadtConDecl dom] -> Decl dom
 mkGadtDataInstance keyw instRule kind cons 
   = mkAnn (child <> " instance " <> child <> child <> " where " <> child) 
-      $ UGDataInstDecl keyw instRule (mkAnnMaybe (optBefore " ") kind) (mkAnnList indentedList cons)
+      $ UGDataInstDecl keyw instRule (mkAnnMaybe (after " " opt) kind) (mkAnnList (indented list) cons)
 
 -- * Pattern synonyms
 
 -- | Creates a pattern synonym (@ pattern Arrow t1 t2 = App \"->\" [t1, t2] @)
 mkPatternSynonym :: PatSynLhs dom -> PatSynRhs dom -> Decl dom
-mkPatternSynonym lhs rhs = mkAnn child $ UPatternSynonymDecl $ mkAnn ("pattern " <> child <> " " <> child) $ UPatternSynonym lhs rhs
+mkPatternSynonym lhs rhs = mkAnn child $ UPatternSynonymDecl $ mkAnn ("pattern " <> child <> " " <> child) 
+                                                             $ UPatternSynonym lhs rhs
 
 -- | Creates a left hand side of a pattern synonym with a constructor name and arguments (@ Arrow t1 t2 @)
 mkConPatSyn :: Name dom -> [Name dom] -> PatSynLhs dom
-mkConPatSyn con args = mkAnn (child <> child) $ UNormalPatSyn con $ mkAnnList (listSepBefore " " " ") args
+mkConPatSyn con args = mkAnn (child <> child) $ UNormalPatSyn con $ mkAnnList (after " " $ separatedBy " " list) args
 
 -- | Creates an infix pattern synonym left-hand side (@ t1 :+: t2 @)
 mkInfixPatSyn :: Name dom -> Operator dom -> Name dom -> PatSynLhs dom
@@ -372,7 +380,8 @@
 
 -- | Creates a record-style pattern synonym left-hand side (@ Arrow { arrowFrom, arrowTo } @)
 mkRecordPatSyn :: Name dom -> [Name dom] -> PatSynLhs dom
-mkRecordPatSyn con args = mkAnn (child <> child) $ URecordPatSyn con $ mkAnnList (listSepBeforeAfter ", " "{ " " }") args
+mkRecordPatSyn con args 
+  = mkAnn (child <> child) $ URecordPatSyn con $ mkAnnList (after "{ " $ separatedBy ", " $ followedBy " }" list) args
 
 -- | Creates an automatically two-way pattern synonym (@ = App \"Int\" [] @)
 mkSymmetricPatSyn :: Pattern dom -> PatSynRhs dom
@@ -384,8 +393,8 @@
 
 -- | Creates a pattern synonym with the other direction explicitely specified (@ <- App \"Int\" [] where Int = App \"Int\" [] @)
 mkTwoWayPatSyn :: Pattern dom -> [Match dom] -> PatSynRhs dom
-mkTwoWayPatSyn pat match = mkAnn ("<- " <> child <> child) $ UBidirectionalPatSyn pat $ mkAnnMaybe (optBefore " where ") 
-                             $ Just $ mkAnn child $ UPatSynWhere $ mkAnnList indentedList match
+mkTwoWayPatSyn pat match = mkAnn ("<- " <> child <> child) $ UBidirectionalPatSyn pat $ mkAnnMaybe (after " where " opt) 
+                             $ Just $ mkAnn child $ UPatSynWhere $ mkAnnList (indented list) match
 
 -- | Creates a pattern type signature declaration (@ pattern Succ :: Int -> Int @)
 mkPatternSignatureDecl :: PatternSignature dom -> Decl dom
@@ -402,17 +411,17 @@
 
 -- | A pragma that introduces source rewrite rules (@ {-\# RULES "map/map" [2]  forall f g xs. map f (map g xs) = map (f.g) xs \#-} @)
 mkRulePragma :: [Rule dom] -> TopLevelPragma dom
-mkRulePragma = mkAnn ("{-# RULES " <> child <> " #-}") . URulePragma . mkAnnList (listSep ", ")
+mkRulePragma = mkAnn ("{-# RULES " <> child <> " #-}") . URulePragma . mkAnnList (separatedBy ", " list)
 
 -- | A pragma that marks definitions as deprecated (@ {-\# DEPRECATED f "f will be replaced by g" \#-} @)
 mkDeprPragma :: [Name dom] -> String -> TopLevelPragma dom
 mkDeprPragma defs msg = mkAnn ("{-# DEPRECATED " <> child <> " " <> child <> " #-}") 
-                          $ UDeprPragma (mkAnnList (listSep ", ") defs) $ mkAnn ("\"" <> child <> "\"") $ UStringNode msg
+                          $ UDeprPragma (mkAnnList (separatedBy ", " list) defs) $ mkAnn ("\"" <> child <> "\"") $ UStringNode msg
 
 -- | A pragma that marks definitions as deprecated (@ {-\# WARNING unsafePerformIO "you should know what you are doing" \#-} @)
 mkWarningPragma :: [Name dom] -> String -> TopLevelPragma dom
 mkWarningPragma defs msg = mkAnn ("{-# WARNING " <> child <> " " <> child <> " #-}") 
-                             $ UWarningPragma (mkAnnList (listSep ", ") defs) $ mkAnn ("\"" <> child <> "\"") $ UStringNode msg
+                             $ UWarningPragma (mkAnnList (separatedBy ", " list) defs) $ mkAnn ("\"" <> child <> "\"") $ UStringNode msg
 
 -- | A pragma that annotates a definition with an arbitrary value (@ {-\# ANN f 42 \#-} @)
 mkAnnPragma :: AnnotationSubject dom -> Expr dom -> TopLevelPragma dom
@@ -422,31 +431,31 @@
 mkInlinePragma :: Maybe (ConlikeAnnot dom) -> Maybe (PhaseControl dom) -> Name dom -> TopLevelPragma dom
 mkInlinePragma conlike phase name 
   = mkAnn ("{-# INLINE " <> child <> child <> child <> " #-}") 
-      $ UInlinePragma (mkAnnMaybe (optAfter " ") conlike) (mkAnnMaybe (optAfter " ") phase) name
+      $ UInlinePragma (mkAnnMaybe (followedBy " " opt) conlike) (mkAnnMaybe (followedBy " " opt) phase) name
 
 -- | A pragma that forbids a function from being inlined by the compiler (@ {-\# NOINLINE f \#-} @)
 mkNoInlinePragma :: Maybe (ConlikeAnnot dom) -> Maybe (PhaseControl dom) -> Name dom -> TopLevelPragma dom
 mkNoInlinePragma conlike phase name 
   = mkAnn ("{-# NOINLINE " <> child <> child <> child <> " #-}") 
-     $ UNoInlinePragma (mkAnnMaybe (optAfter " ") conlike) (mkAnnMaybe (optAfter " ") phase) name
+     $ UNoInlinePragma (mkAnnMaybe (followedBy " " opt) conlike) (mkAnnMaybe (followedBy " " opt) phase) name
 
 -- | A pragma that marks a function that it may be inlined by the compiler (@ {-\# INLINABLE thenUs \#-} @)
 mkInlinablePragma :: Maybe (PhaseControl dom) -> Name dom -> TopLevelPragma dom
 mkInlinablePragma phase name
   = mkAnn ("{-# INLINEABLE " <> child <> child <> " #-}") 
-     $ UInlinablePragma (mkAnnMaybe (optAfter " ") phase) name
+     $ UInlinablePragma (mkAnnMaybe (followedBy " " opt) phase) name
 
 -- | A pragma for maintaining line numbers in generated sources (@ {-\# LINE 123 "somefile" \#-} @)
 mkLinePragma :: Int -> Maybe (StringNode dom) -> TopLevelPragma dom
 mkLinePragma line filename 
   = mkAnn ("{-# LINE " <> child <> child <> " #-}") 
-     $ ULinePragma (mkAnn child $ LineNumber line) (mkAnnMaybe (optBefore " ") filename)
+     $ ULinePragma (mkAnn child $ LineNumber line) (mkAnnMaybe (after " " opt) filename)
 
 -- | A pragma that tells the compiler that a polymorph function should be optimized for a given type (@ {-\# SPECIALISE f :: Int -> b -> b \#-} @)
 mkSpecializePragma :: Maybe (PhaseControl dom) -> Name dom -> [Type dom] -> TopLevelPragma dom
 mkSpecializePragma phase def specTypes 
   = mkAnn ("{-# SPECIALIZE " <> child <> child <> " " <> child <> " #-}") 
-     $ USpecializePragma (mkAnnMaybe (optBefore " ") phase) def $ mkAnnList (listSep ", ") specTypes
+     $ USpecializePragma (mkAnnMaybe (after " " opt) phase) def $ mkAnnList (separatedBy ", " list) specTypes
 
 -- | Marks that the pragma should be applied from a given compile phase (@ [2] @)
 mkPhaseControlFrom :: Integer -> PhaseControl dom
@@ -463,8 +472,8 @@
 mkRewriteRule :: String -> Maybe (PhaseControl dom) -> [TyVar dom] -> Expr dom -> Expr dom -> Rule dom
 mkRewriteRule name phase vars lhs rhs
   = mkAnn (child <> " " <> child <> child <> child <> " = " <> child)
-      $ URule (mkAnn ("\"" <> child <> "\"") $ UStringNode name) (mkAnnMaybe (optAfter " ") phase)
-              (mkAnnList (listSepBeforeAfter " " "forall " ". ") vars) lhs rhs
+      $ URule (mkAnn ("\"" <> child <> "\"") $ UStringNode name) (mkAnnMaybe (followedBy " " opt) phase)
+              (mkAnnList (after "forall " $ separatedBy " " $ followedBy ". " list) vars) lhs rhs
 
 -- | The definition with the given name is annotated
 mkNameAnnotation :: Name dom -> AnnotationSubject dom
diff --git a/Language/Haskell/Tools/AST/Gen/Exprs.hs b/Language/Haskell/Tools/AST/Gen/Exprs.hs
--- a/Language/Haskell/Tools/AST/Gen/Exprs.hs
+++ b/Language/Haskell/Tools/AST/Gen/Exprs.hs
@@ -41,11 +41,11 @@
 
 -- | Create a lambda expression (@ \\a b -> a + b @)
 mkLambda :: [Pattern dom] -> Expr dom -> Expr dom
-mkLambda pats rhs = mkAnn ("\\" <> child <> " -> " <> child) $ ULambda (mkAnnList (listSep " ") pats) rhs
+mkLambda pats rhs = mkAnn ("\\" <> child <> " -> " <> child) $ ULambda (mkAnnList (separatedBy " " list) pats) rhs
 
 -- | Create a local binding (@ let x = 2; y = 3 in e x y @)
 mkLet :: [LocalBind dom] -> Expr dom -> Expr dom
-mkLet pats expr = mkAnn ("let " <> child <> " in " <> child) $ ULet (mkAnnList indentedList pats) expr
+mkLet pats expr = mkAnn ("let " <> child <> " in " <> child) $ ULet (mkAnnList (indented list) pats) expr
 
 -- | Create a if expression (@ if a then b else c @)
 mkIf :: Expr dom -> Expr dom -> Expr dom -> Expr dom
@@ -53,43 +53,43 @@
 
 -- | Create a multi way if expressions with @MultiWayIf@ extension (@ if | guard1 -> expr1; guard2 -> expr2 @)
 mkMultiIf :: [GuardedCaseRhs dom] -> Expr dom
-mkMultiIf cases = mkAnn ("if" <> child) $ UMultiIf (mkAnnList indentedList cases)
+mkMultiIf cases = mkAnn ("if" <> child) $ UMultiIf (mkAnnList (indented list) cases)
 
 -- | Create a pattern matching expression (@ case expr of pat1 -> expr1; pat2 -> expr2 @)
 mkCase :: Expr dom -> [Alt dom] -> Expr dom
-mkCase expr cases = mkAnn ("case " <> child <> " of " <> child) $ UCase expr (mkAnnList indentedList cases)
+mkCase expr cases = mkAnn ("case " <> child <> " of " <> child) $ UCase expr (mkAnnList (indented list) cases)
 
 -- | Create a do-notation expressions (@ do x <- act1; act2 @)
 mkDoBlock :: [Stmt dom] -> Expr dom
-mkDoBlock stmts = mkAnn (child <> " " <> child) $ UDo (mkAnn "do" UDoKeyword) (mkAnnList indentedList stmts)
+mkDoBlock stmts = mkAnn (child <> " " <> child) $ UDo (mkAnn "do" UDoKeyword) (mkAnnList (indented list) stmts)
 
 -- | Create a tuple expression (@ (e1, e2, e3) @)
 mkTuple :: [Expr dom] -> Expr dom
-mkTuple exprs = mkAnn ("(" <> child <> ")") $ UTuple (mkAnnList (listSep ", ") exprs)
+mkTuple exprs = mkAnn ("(" <> child <> ")") $ UTuple (mkAnnList (separatedBy ", " list) exprs)
 
 -- | Create a unboxed tuple expression (@ (\# e1, e2, e3 \#) @)
 mkUnboxedTuple :: [Expr dom] -> Expr dom
-mkUnboxedTuple exprs = mkAnn ("(# " <> child <> " #)") $ UTuple (mkAnnList (listSep ", ") exprs)
+mkUnboxedTuple exprs = mkAnn ("(# " <> child <> " #)") $ UTuple (mkAnnList (separatedBy ", " list) exprs)
 
 -- | Create a tuple section, enabled with @TupleSections@ (@ (a,,b) @). One of the elements must be missing.
 mkTupleSection :: [Maybe (Expr dom)] -> Expr dom
 mkTupleSection elems 
   = let tupSecs = map (maybe (mkAnn "" Missing) (mkAnn child . Present)) elems
-     in mkAnn ("(" <> child <> ")") $ UTupleSection (mkAnnList (listSep ", ") tupSecs)
+     in mkAnn ("(" <> child <> ")") $ UTupleSection (mkAnnList (separatedBy ", " list) tupSecs)
 
 -- | Create a unboxed tuple section, enabled with @TupleSections@ (@ (\#a,,b\#) @). One of the elements must be missing.
 mkTupleUnboxedSection :: [Maybe (Expr dom)] -> Expr dom
 mkTupleUnboxedSection elems 
   = let tupSecs = map (maybe (mkAnn "" Missing) (mkAnn child . Present)) elems
-     in mkAnn ("(" <> child <> ")") $ UTupleSection (mkAnnList (listSep ", ") tupSecs)
+     in mkAnn ("(" <> child <> ")") $ UTupleSection (mkAnnList (separatedBy ", " list) tupSecs)
 
 -- | Create a list expression: @[1,2,3]@
 mkList :: [Expr dom] -> Expr dom
-mkList exprs = mkAnn ("[" <> child <> "]") $ UList (mkAnnList (listSep ", ") exprs)
+mkList exprs = mkAnn ("[" <> child <> "]") $ UList (mkAnnList (separatedBy ", " list) exprs)
 
 -- | Create a parallel array expression: @[: 1,2,3 :]@
 mkParArray :: [Expr dom] -> Expr dom
-mkParArray exprs = mkAnn ("[: " <> child <> " :]") $ UParArray (mkAnnList (listSep ", ") exprs)
+mkParArray exprs = mkAnn ("[: " <> child <> " :]") $ UParArray (mkAnnList (separatedBy ", " list) exprs)
 
 -- | Create a parenthesized expression: @( a + b )@
 mkParen :: Expr dom -> Expr dom
@@ -105,33 +105,33 @@
 
 -- | Create a record value construction: @Point { x = 3, y = -2 }@
 mkRecCon :: Name dom -> [FieldUpdate dom] -> Expr dom
-mkRecCon name flds = mkAnn (child <> " { " <> child <> " }") $ URecCon name (mkAnnList (listSep ", ") flds)
+mkRecCon name flds = mkAnn (child <> " { " <> child <> " }") $ URecCon name (mkAnnList (separatedBy ", " list) flds)
 
 -- | Create a record value  update: @p1 { x = 3, y = -2 }@
 mkRecUpdate :: Expr dom -> [FieldUpdate dom] -> Expr dom
-mkRecUpdate expr flds = mkAnn (child <> " { " <> child <> " }") $ URecUpdate expr (mkAnnList (listSep ", ") flds)
+mkRecUpdate expr flds = mkAnn (child <> " { " <> child <> " }") $ URecUpdate expr (mkAnnList (separatedBy ", " list) flds)
 
 -- | Create a enumeration expression (@ [1,3..10] @)
 mkEnum :: Expr dom -> Maybe (Expr dom) -> Maybe (Expr dom) -> Expr dom
-mkEnum from step to = mkAnn ("[" <> child <> child <> ".." <> child <> "]") $ UEnum from (mkAnnMaybe (optBefore ",") step) (mkAnnMaybe (optBefore ",") to)
+mkEnum from step to = mkAnn ("[" <> child <> child <> ".." <> child <> "]") $ UEnum from (mkAnnMaybe (after "," opt) step) (mkAnnMaybe (after "," opt) to)
 
 -- | Create a parallel array enumeration (@ [: 1,3 .. 10 :] @)
 mkParArrayEnum :: Expr dom -> Maybe (Expr dom) -> Expr dom -> Expr dom
 mkParArrayEnum from step to
   = mkAnn ("[: " <> child <> child <> ".." <> child <> " :]") 
-      $ UParArrayEnum from (mkAnnMaybe (optBefore ",") step) to
+      $ UParArrayEnum from (mkAnnMaybe (after "," opt) step) to
 
 -- | Create a list comprehension (@ [ (x, y) | x <- xs | y <- ys ] @)
 mkListComp :: Expr dom -> [ListCompBody dom] -> Expr dom
 mkListComp expr stmts 
   = mkAnn ("[ " <> child <> " | " <> child <> " ]") 
-      $ UListComp expr $ mkAnnList (listSep " | ") stmts
+      $ UListComp expr $ mkAnnList (separatedBy " | " list) stmts
 
 -- | Create a parallel array comprehensions @ [: (x, y) | x <- xs , y <- ys :] @ enabled by @ParallelArrays@
 mkParArrayComp :: Expr dom -> [ListCompBody dom] -> Expr dom
 mkParArrayComp expr stmts 
   = mkAnn ("[: " <> child <> " | " <> child <> " :]") 
-      $ UParArrayComp expr $ mkAnnList (listSep " | ") stmts
+      $ UParArrayComp expr $ mkAnnList (separatedBy " | " list) stmts
 
 -- | Create a explicit type signature (@ x :: Int @)
 mkExprTypeSig :: Expr dom -> Type dom -> Expr dom
@@ -175,7 +175,7 @@
 
 -- | Create a lambda case ( @\case 0 -> 1; 1 -> 2@ )
 mkLambdaCase :: [Alt dom] -> Expr dom
-mkLambdaCase = mkAnn ("\\case" <> child) . ULamCase . mkAnnList indentedList
+mkLambdaCase = mkAnn ("\\case" <> child) . ULamCase . mkAnnList (indented list)
 
 -- | Create a static pointer expression (@ static e @). The inner expression must be closed (cannot have variables bound outside)
 mkStaticPointer :: Expr dom -> Expr dom
@@ -202,7 +202,7 @@
 
 -- | Create a clause of case expression (@ Just x -> x + 1 @)
 mkAlt :: Pattern dom -> CaseRhs dom -> Maybe (LocalBinds dom) -> Alt dom
-mkAlt pat rhs locals = mkAnn (child <> child <> child) $ UAlt pat rhs (mkAnnMaybe (optBefore " where ") locals)
+mkAlt pat rhs locals = mkAnn (child <> child <> child) $ UAlt pat rhs (mkAnnMaybe (after " where " opt) locals)
 
 -- | Create a unguarded right-hand side a pattern match (@ -> 3 @)
 mkCaseRhs :: Expr dom -> CaseRhs dom
@@ -210,11 +210,11 @@
 
 -- | Create a guarded right-hand sides of a pattern match (@ | x == 1 -> 3; | otherwise -> 4 @)
 mkGuardedCaseRhss :: [GuardedCaseRhs dom] -> CaseRhs dom
-mkGuardedCaseRhss = mkAnn child . UGuardedCaseRhss . mkAnnList indentedList
+mkGuardedCaseRhss = mkAnn child . UGuardedCaseRhss . mkAnnList (indented list)
 
 -- | Creates a guarded right-hand side of pattern matches binding (@ | x > 3 -> 2 @)      
 mkGuardedCaseRhs :: [RhsGuard dom] -> Expr dom -> GuardedCaseRhs dom
-mkGuardedCaseRhs guards expr = mkAnn (" | " <> child <> " -> " <> child) $ UGuardedCaseRhs (mkAnnList (listSep ", ") guards) expr
+mkGuardedCaseRhs guards expr = mkAnn (" | " <> child <> " -> " <> child) $ UGuardedCaseRhs (mkAnnList (separatedBy ", " list) guards) expr
 
 -- * Pragmas that can be applied to expressions
 
@@ -252,7 +252,7 @@
 mkArrowFromCmd :: Expr dom -> [Cmd dom] -> Cmd dom
 mkArrowFromCmd expr cmds 
   = mkAnn ("(| " <> child <> child <> " |)")
-      $ UArrowFormCmd expr $ mkAnnList (listSepBefore " " " ") cmds
+      $ UArrowFormCmd expr $ mkAnnList (after " " $ separatedBy " " list) cmds
 
 -- | A function application command
 mkAppCmd :: Cmd dom -> Expr dom -> Cmd dom
@@ -267,7 +267,7 @@
 -- | A lambda command 
 mkLambdaCmd :: [Pattern dom] -> Cmd dom -> Cmd dom
 mkLambdaCmd args cmd = mkAnn ("\\" <> child <> " -> " <> child)
-                         $ ULambdaCmd (mkAnnList (listSep " ") args) cmd
+                         $ ULambdaCmd (mkAnnList (separatedBy " " list) args) cmd
 
 -- | A parenthesized command
 mkParenCmd :: Cmd dom -> Cmd dom
@@ -277,7 +277,7 @@
 mkCaseCmd :: Expr dom -> [CmdAlt dom] -> Cmd dom
 mkCaseCmd expr alts 
   = mkAnn ("case " <> child <> " of " <> child) 
-      $ UCaseCmd expr $ mkAnnList indentedList alts
+      $ UCaseCmd expr $ mkAnnList (indented list) alts
 
 -- | An if command (@ if f x y then g -< x+1 else h -< y+2 @)
 mkIfCmd :: Expr dom -> Cmd dom -> Cmd dom -> Cmd dom
@@ -289,11 +289,11 @@
 mkLetCmd :: [LocalBind dom] -> Cmd dom -> Cmd dom
 mkLetCmd binds cmd
   = mkAnn ("let " <> child <> " in " <> child) 
-      $ ULetCmd (mkAnnList indentedList binds) cmd
+      $ ULetCmd (mkAnnList (indented list) binds) cmd
 
 -- | A do-notation in a command
 mkDoCmd :: [CmdStmt dom] -> Cmd dom
-mkDoCmd stmts = mkAnn ("do " <> child) $ UDoCmd (mkAnnList indentedList stmts)
+mkDoCmd stmts = mkAnn ("do " <> child) $ UDoCmd (mkAnnList (indented list) stmts)
 
 -- | Left arrow application: @-<@
 mkLeftAppl :: ArrowApp dom
diff --git a/Language/Haskell/Tools/AST/Gen/Kinds.hs b/Language/Haskell/Tools/AST/Gen/Kinds.hs
--- a/Language/Haskell/Tools/AST/Gen/Kinds.hs
+++ b/Language/Haskell/Tools/AST/Gen/Kinds.hs
@@ -62,11 +62,11 @@
 
 -- | A list of elements as a kind.
 mkListKind :: [Kind dom] -> Kind dom
-mkListKind = mkAnn child . UPromotedKind . mkAnn ("[" <> child <> "]") . UPromotedList . mkAnnList (listSep ", ")
+mkListKind = mkAnn child . UPromotedKind . mkAnn ("[" <> child <> "]") . UPromotedList . mkAnnList (separatedBy ", " list)
 
 -- | A tuple of elements as a kind.
 mkTupleKind :: [Kind dom] -> Kind dom
-mkTupleKind = mkAnn child . UPromotedKind . mkAnn ("(" <> child <> ")") . UPromotedTuple . mkAnnList (listSep ", ")
+mkTupleKind = mkAnn child . UPromotedKind . mkAnn ("(" <> child <> ")") . UPromotedTuple . mkAnnList (separatedBy ", " list)
 
 -- | Kind of the unit value @()@. 
 mkUnitKind :: Kind dom
diff --git a/Language/Haskell/Tools/AST/Gen/Modules.hs b/Language/Haskell/Tools/AST/Gen/Modules.hs
--- a/Language/Haskell/Tools/AST/Gen/Modules.hs
+++ b/Language/Haskell/Tools/AST/Gen/Modules.hs
@@ -22,16 +22,17 @@
 mkModule :: [FilePragma dom] -> Maybe (ModuleHead dom) -> [ImportDecl dom] -> [Decl dom] -> Module dom
 mkModule filePrags head imps decls 
   = mkAnn (child <> child <> child <> child) 
-      $ UModule (mkAnnList (listSepAfter "\n" "\n") filePrags) (mkAnnMaybe opt head)
-                (mkAnnList (indentedListBefore "\n") imps) (mkAnnList (indentedListBefore "\n") decls)
+      $ UModule (mkAnnList (followedBy "\n" $ separatedBy "\n" list) filePrags) (mkAnnMaybe opt head)
+                (mkAnnList (after "\n" $ indented list) imps) (mkAnnList (after "\n" $ indented list) decls)
                
 -- | Module declaration with name and (optional) exports
 mkModuleHead :: ModuleName dom -> Maybe (ExportSpecs dom) -> Maybe (ModulePragma dom) -> ModuleHead dom
-mkModuleHead n es pr = mkAnn ("module " <> child <> child <> child <> " where") $ UModuleHead n (mkAnnMaybe opt es) (mkAnnMaybe (optBefore "\n") pr)
+mkModuleHead n es pr = mkAnn ("module " <> child <> child <> child <> " where") 
+                         $ UModuleHead n (mkAnnMaybe opt es) (mkAnnMaybe (after "\n" opt) pr)
 
 -- | A list of export specifications surrounded by parentheses
 mkExportSpecs :: [ExportSpec dom] -> ExportSpecs dom
-mkExportSpecs = mkAnn ("(" <> child <> ")") . UExportSpecs . mkAnnList (listSep ", ")
+mkExportSpecs = mkAnn ("(" <> child <> ")") . UExportSpecs . mkAnnList (separatedBy ", " list)
 
 -- | Export a name and related names
 mkExportSpec :: IESpec dom -> ExportSpec dom
@@ -43,15 +44,15 @@
 
 -- | Marks a name to be imported or exported with related names (subspecifier)
 mkIESpec :: Name dom -> Maybe (SubSpec dom) -> IESpec dom
-mkIESpec name ss = mkAnn (child <> child) (UIESpec name (mkAnnMaybe opt ss))
+mkIESpec name ss = mkAnn (child <> child) (UIESpec name (mkAnnMaybe (after "(" $ followedBy ")" opt) ss))
 
 -- | @(a,b,c)@: a class exported with some of its methods, or a datatype exported with some of its constructors.
 mkSubList :: [Name dom] -> SubSpec dom
-mkSubList = mkAnn ("(" <> child <> ")") . USubSpecList . mkAnnList (listSep ", ")
+mkSubList = mkAnn child . USubSpecList . mkAnnList (separatedBy ", " list)
 
 -- | @(..)@: a class exported with all of its methods, or a datatype exported with all of its constructors.
 mkSubAll :: SubSpec dom
-mkSubAll = mkAnn "(..)" USubSpecAll
+mkSubAll = mkAnn ".." USubSpecAll
 
 -- | An import declaration: @import Module.Name@         
 mkImportDecl :: Bool -> Bool -> Bool -> Maybe String -> ModuleName dom -> Maybe (ModuleName dom) -> Maybe (ImportSpec dom) 
@@ -66,11 +67,11 @@
 
 -- | Restrict the import definition to ONLY import the listed names
 mkImportSpecList :: [IESpec dom] -> ImportSpec dom
-mkImportSpecList = mkAnn ("(" <> child <> ")") . UImportSpecList . mkAnnList (listSep ", ")
+mkImportSpecList = mkAnn ("(" <> child <> ")") . UImportSpecList . mkAnnList (separatedBy ", " list)
 
 -- | Restrict the import definition to DONT import the listed names
 mkImportHidingList :: [IESpec dom] -> ImportSpec dom
-mkImportHidingList = mkAnn (" hiding (" <> child <> ")") . UImportSpecHiding . mkAnnList (listSep ", ")
+mkImportHidingList = mkAnn (" hiding (" <> child <> ")") . UImportSpecHiding . mkAnnList (separatedBy ", " list)
 
 -- | The name of a module
 mkModuleName :: String -> ModuleName dom
@@ -82,7 +83,7 @@
 mkLanguagePragma :: [String] -> FilePragma dom
 mkLanguagePragma extensions 
   = mkAnn ("{-# LANGUAGE " <> child <> " #-}") $ ULanguagePragma 
-      $ mkAnnList (listSep ", ") (map (\ext -> mkAnn (fromString ext) (ULanguageExtension ext)) extensions)
+      $ mkAnnList (separatedBy ", " list) (map (\ext -> mkAnn (fromString ext) (ULanguageExtension ext)) extensions)
 
 -- | @OPTIONS@ pragma, possibly qualified with a tool, e.g. OPTIONS_GHC
 mkOptionsGHC :: String -> FilePragma dom
@@ -94,10 +95,10 @@
 mkModuleWarningPragma :: [String] -> ModulePragma dom
 mkModuleWarningPragma msg 
   = mkAnn ("{-# WARNING " <> child <> " #-}") $ UModuleWarningPragma 
-      $ mkAnnList (listSep " ") $ map mkStringNode msg
+      $ mkAnnList (separatedBy " " list) $ map mkStringNode msg
 
 -- | A deprecated pragma attached to the module
 mkModuleDeprecatedPragma :: [String] -> ModulePragma dom
 mkModuleDeprecatedPragma msg 
   = mkAnn ("{-# DEPRECATED " <> child <> " #-}") $ UModuleDeprecatedPragma 
-      $ mkAnnList (listSep " ") $ map mkStringNode msg
+      $ mkAnnList (separatedBy " " list) $ map mkStringNode msg
diff --git a/Language/Haskell/Tools/AST/Gen/Names.hs b/Language/Haskell/Tools/AST/Gen/Names.hs
--- a/Language/Haskell/Tools/AST/Gen/Names.hs
+++ b/Language/Haskell/Tools/AST/Gen/Names.hs
@@ -68,7 +68,7 @@
 mkQualifiedName [] n = mkSimpleName n
 mkQualifiedName quals name
   = mkAnn (child <> "." <> child)
-          (UQualifiedName (mkAnnList (listSep ".") $ map mkNamePart quals) (mkNamePart name))
+          (UQualifiedName (mkAnnList (separatedBy "." list) $ map mkNamePart quals) (mkNamePart name))
 
 -- | Creates a part of a qualified name.         
 mkNamePart :: String -> NamePart dom
diff --git a/Language/Haskell/Tools/AST/Gen/Patterns.hs b/Language/Haskell/Tools/AST/Gen/Patterns.hs
--- a/Language/Haskell/Tools/AST/Gen/Patterns.hs
+++ b/Language/Haskell/Tools/AST/Gen/Patterns.hs
@@ -31,23 +31,23 @@
 
 -- | Constructor application pattern (@ Point x y @)
 mkAppPat :: Name dom -> [Pattern dom] -> Pattern dom
-mkAppPat n pat = mkAnn (child <> child) $ UAppPat n (mkAnnList (listSepBefore " " " ") pat)
+mkAppPat n pat = mkAnn (child <> child) $ UAppPat n (mkAnnList (after " " $ separatedBy " " list) pat)
 
 -- | Tuple pattern (@ (x,y) @)
 mkTuplePat :: [Pattern dom] -> Pattern dom
-mkTuplePat pats = mkAnn ("(" <> child <> ")") $ UTuplePat (mkAnnList (listSep ", ") pats)
+mkTuplePat pats = mkAnn ("(" <> child <> ")") $ UTuplePat (mkAnnList (separatedBy ", " list) pats)
 
 -- | Unboxed tuple pattern (@ (\# x, y \#) @)
 mkUnboxTuplePat :: [Pattern dom] -> Pattern dom
-mkUnboxTuplePat pats = mkAnn ("(# " <> child <> " #)") $ UUnboxTuplePat (mkAnnList (listSep ", ") pats)
+mkUnboxTuplePat pats = mkAnn ("(# " <> child <> " #)") $ UUnboxTuplePat (mkAnnList (separatedBy ", " list) pats)
 
 -- | List pattern (@ [1,2,a,x] @)
 mkListPat :: [Pattern dom] -> Pattern dom
-mkListPat pats = mkAnn ("[" <> child <> "]") $ UListPat (mkAnnList (listSep ", ") pats)
+mkListPat pats = mkAnn ("[" <> child <> "]") $ UListPat (mkAnnList (separatedBy ", " list) pats)
 
 -- | Parallel array pattern (@ [:1,2,a,x:] @)
 mkParArrayPat :: [Pattern dom] -> Pattern dom
-mkParArrayPat pats = mkAnn ("[:" <> child <> ":]") $ UParArrPat (mkAnnList (listSep ", ") pats)
+mkParArrayPat pats = mkAnn ("[:" <> child <> ":]") $ UParArrPat (mkAnnList (separatedBy ", " list) pats)
 
 -- | Parenthesised patterns
 mkParenPat :: Pattern dom -> Pattern dom
@@ -55,7 +55,7 @@
 
 -- | Record pattern (@ Point { x = 3, y } @)
 mkRecPat :: Name dom -> [PatternField dom] -> Pattern dom
-mkRecPat name flds = mkAnn (child <> "{ " <> child <> " }") $ URecPat name (mkAnnList (listSep ", ") flds)
+mkRecPat name flds = mkAnn (child <> "{ " <> child <> " }") $ URecPat name (mkAnnList (separatedBy ", " list) flds)
 
 -- | As-pattern (explicit name binding) (@ ls\@(hd:_) @)
 mkAsPat :: Name dom -> Pattern dom -> Pattern dom
diff --git a/Language/Haskell/Tools/AST/Gen/Stmts.hs b/Language/Haskell/Tools/AST/Gen/Stmts.hs
--- a/Language/Haskell/Tools/AST/Gen/Stmts.hs
+++ b/Language/Haskell/Tools/AST/Gen/Stmts.hs
@@ -26,17 +26,17 @@
 
 -- | Creates a let statement (@ let x = 3; y = 4 @)
 mkLetStmt :: [LocalBind dom] -> Stmt dom
-mkLetStmt = mkAnn ("let " <> child) . ULetStmt . mkAnnList indentedList
+mkLetStmt = mkAnn ("let " <> child) . ULetStmt . mkAnnList (indented list)
 
 -- | Creates a recursive binding statement with (@ rec b <- f a c; c <- f b a @)
 mkRecStmt :: [Stmt dom] -> Stmt dom
-mkRecStmt = mkAnn ("rec " <> child) . URecStmt . mkAnnList indentedList
+mkRecStmt = mkAnn ("rec " <> child) . URecStmt . mkAnnList (indented list)
 
 -- * List comprehensions
 
 -- | Body of a list comprehension: (@ | x <- [1..10] @)
 mkListCompBody :: [CompStmt dom] -> ListCompBody dom
-mkListCompBody = mkAnn child . UListCompBody . mkAnnList (listSep " ")
+mkListCompBody = mkAnn child . UListCompBody . mkAnnList (separatedBy " " list)
 
 -- | Normal monadic statement of a list comprehension
 mkCompStmt :: Stmt dom -> CompStmt dom
@@ -45,13 +45,13 @@
 -- | Then statements by @TransformListComp@ (@ then sortWith by (x + y) @)
 mkThenStmt :: Expr dom -> Maybe (Expr dom) -> CompStmt dom
 mkThenStmt th by = mkAnn ("then " <> child) 
-                     $ UThenStmt th $ mkAnnMaybe (optBefore " by ") by
+                     $ UThenStmt th $ mkAnnMaybe (after " by " opt) by
 
 -- | Grouping statements by @TransformListComp@ (@ then group by (x + y) using groupWith @) 
 mkGroupStmt :: Maybe (Expr dom) -> Maybe (Expr dom) -> CompStmt dom
 mkGroupStmt by using = mkAnn ("then group" <> child) 
-                         $ UGroupStmt (mkAnnMaybe (optBefore " by ") by)
-                                      (mkAnnMaybe (optBefore " using ") using)
+                         $ UGroupStmt (mkAnnMaybe (after " by " opt) by)
+                                      (mkAnnMaybe (after " using " opt) using)
 
 -- * Commands
 
@@ -65,9 +65,9 @@
 
 -- | Creates a let command (@ let x = 3; y = 4 @)
 mkLetStmtCmd :: [LocalBind dom] -> CmdStmt dom
-mkLetStmtCmd = mkAnn ("let " <> child) . ULetStmt . mkAnnList indentedList
+mkLetStmtCmd = mkAnn ("let " <> child) . ULetStmt . mkAnnList (indented list)
 
 -- | Creates a recursive binding command with (@ rec b <- f a c; c <- f b a @)
 mkRecCmd :: [CmdStmt dom] -> CmdStmt dom
-mkRecCmd = mkAnn ("rec " <> child) . URecStmt . mkAnnList indentedList
+mkRecCmd = mkAnn ("rec " <> child) . URecStmt . mkAnnList (indented list)
 
diff --git a/Language/Haskell/Tools/AST/Gen/TH.hs b/Language/Haskell/Tools/AST/Gen/TH.hs
--- a/Language/Haskell/Tools/AST/Gen/TH.hs
+++ b/Language/Haskell/Tools/AST/Gen/TH.hs
@@ -42,5 +42,5 @@
 
 -- | Declaration bracket (@ [d| f :: Int -> Int; f x = x*x |] @)
 mkDeclsBracket :: [Decl dom] -> Bracket dom
-mkDeclsBracket = mkAnn ("[d|" <> child <> "|]") . UDeclsBracket . mkAnnList indentedList
+mkDeclsBracket = mkAnn ("[d|" <> child <> "|]") . UDeclsBracket . mkAnnList (indented list)
 
diff --git a/Language/Haskell/Tools/AST/Gen/Types.hs b/Language/Haskell/Tools/AST/Gen/Types.hs
--- a/Language/Haskell/Tools/AST/Gen/Types.hs
+++ b/Language/Haskell/Tools/AST/Gen/Types.hs
@@ -22,7 +22,7 @@
 
 -- | Forall types (@ forall x y . type @)
 mkForallType :: [TyVar dom] -> Type dom -> Type dom
-mkForallType vars t = mkAnn ("forall " <> child <> " . " <> child) (UTyForall (mkAnnList (listSep " ") vars) t)
+mkForallType vars t = mkAnn ("forall " <> child <> " . " <> child) (UTyForall (mkAnnList (separatedBy " " list) vars) t)
 
 -- | Simplified creation of type variables
 mkTypeVar' :: GHC.Name -> TyVar dom
@@ -38,11 +38,11 @@
 
 -- | Tuple types (@ (a,b) @)
 mkTupleType :: [Type dom] -> Type dom
-mkTupleType args = mkAnn ("(" <> child <> ")") (UTyTuple (mkAnnList (listSep ", ") args))
+mkTupleType args = mkAnn ("(" <> child <> ")") (UTyTuple (mkAnnList (separatedBy ", " list) args))
 
 -- | Unboxed tuple types (@ (\#a,b\#) @)
 mkUnboxedTupleType :: [Type dom] -> Type dom
-mkUnboxedTupleType args = mkAnn ("(#" <> child <> "#)") (UTyUnbTuple (mkAnnList (listSep ", ") args))
+mkUnboxedTupleType args = mkAnn ("(#" <> child <> "#)") (UTyUnbTuple (mkAnnList (separatedBy ", " list) args))
 
 -- | List type with special syntax (@ [a] @)
 mkListType :: Type dom -> Type dom
@@ -127,11 +127,13 @@
 
 -- | A list of elements as a kind.
 mkPromotedListType :: [Type dom] -> Type dom
-mkPromotedListType = mkAnn child . UTyPromoted . mkAnn ("[" <> child <> "]") . UPromotedList . mkAnnList (listSep ", ")
+mkPromotedListType 
+  = mkAnn child . UTyPromoted . mkAnn ("[" <> child <> "]") . UPromotedList . mkAnnList (separatedBy ", " list)
 
 -- | A tuple of elements as a kind.
 mkPromotedTupleType :: [Type dom] -> Type dom
-mkPromotedTupleType = mkAnn child . UTyPromoted . mkAnn ("(" <> child <> ")") . UPromotedTuple . mkAnnList (listSep ", ")
+mkPromotedTupleType 
+  = mkAnn child . UTyPromoted . mkAnn ("(" <> child <> ")") . UPromotedTuple . mkAnnList (separatedBy ", " list)
 
 -- | Kind of the unit value @()@. 
 mkPromotedUnitType :: Type dom
@@ -145,14 +147,14 @@
 
 -- | Creates a context of a set of assertions (@ (C1 a, C2 b) => ... @, but can be one: @ (C a) => ... @)
 mkContextMulti :: [Assertion dom] -> Context dom
-mkContextMulti = mkAnn ("(" <> child <> ") =>") . UContextMulti . mkAnnList (listSep ", ")
+mkContextMulti = mkAnn ("(" <> child <> ") =>") . UContextMulti . mkAnnList (separatedBy ", " list)
 
 -- * Generation of assertions
 
 -- | Class assertion (@Cls x@)
 mkClassAssert :: Name dom -> [Type dom] -> Assertion dom
 -- fixme: class assertion without parameters should not have the last space
-mkClassAssert n args = mkAnn (child <> " " <> child) $ UClassAssert n (mkAnnList (listSep " ") args)
+mkClassAssert n args = mkAnn (child <> " " <> child) $ UClassAssert n (mkAnnList (separatedBy " " list) args)
 
 -- | Infix class assertion, also contains type equations (@ a ~ X y @)
 mkInfixAssert :: Type dom -> Operator dom -> Type dom -> Assertion dom
diff --git a/haskell-tools-rewrite.cabal b/haskell-tools-rewrite.cabal
--- a/haskell-tools-rewrite.cabal
+++ b/haskell-tools-rewrite.cabal
@@ -1,5 +1,5 @@
 name:                haskell-tools-rewrite
-version:             0.3.0.1
+version:             0.4.0.0
 synopsis:            Facilities for generating new parts of the Haskell-Tools AST
 description:         Contains utility functions to generate parts of the Haskell-Tools AST. Generates these elements to be compatible with the source annotations that are already present on the AST. The package is divided into modules based on which language elements can the given module generate. This packages should be used during the transformations to generate parts of the new AST.
 homepage:            https://github.com/haskell-tools/haskell-tools
@@ -12,6 +12,7 @@
 cabal-version:       >=1.10
 
 library
+  ghc-options:         -O2
   exposed-modules:     Language.Haskell.Tools.AST.Rewrite
                      , Language.Haskell.Tools.AST.ElementTypes
                      , Language.Haskell.Tools.AST.Gen
@@ -44,6 +45,21 @@
                      , containers                >= 0.5  && < 0.6
                      , references                >= 0.3  && < 0.4
                      , ghc                       >= 8.0  && < 8.1
-                     , haskell-tools-ast         >= 0.3  && < 0.4
-                     , haskell-tools-prettyprint >= 0.3  && < 0.4
+                     , haskell-tools-ast         >= 0.4  && < 0.5
+                     , haskell-tools-prettyprint >= 0.4  && < 0.5
+  default-language:    Haskell2010
+
+test-suite haskell-tools-rewrite-tests
+  type:                exitcode-stdio-1.0
+  ghc-options:         -with-rtsopts=-M2g
+  hs-source-dirs:      test
+  main-is:             Main.hs  
+  build-depends:       base                      >= 4.9 && < 4.10
+                     , tasty                     >= 0.11 && < 0.12
+                     , tasty-hunit               >= 0.9 && < 0.10
+                     , directory                 >= 1.2 && < 1.3
+                     , filepath                  >= 1.4 && < 2.0
+                     , haskell-tools-ast         >= 0.4 && < 0.5
+                     , haskell-tools-prettyprint >= 0.4 && < 0.5
+                     , haskell-tools-rewrite     >= 0.4 && < 0.5
   default-language:    Haskell2010
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,143 @@
+module Main where
+
+import Test.Tasty
+import Test.Tasty.HUnit
+
+import Language.Haskell.Tools.AST as AST
+import Language.Haskell.Tools.PrettyPrint
+import Language.Haskell.Tools.AST.Rewrite as G
+
+main :: IO ()
+main = defaultMain genTests
+
+genTests :: TestTree
+genTests = testGroup "ast generation tests" 
+             [ testGroup "name tests" testBase
+             , testGroup "expression tests" (map makeGenTest testExprs)
+             , testGroup "pattern tests" (map makeGenTest testPatterns)
+             , testGroup "type tests" (map makeGenTest testType) 
+             , testGroup "binding tests" (map makeGenTest testBinds)
+             , testGroup "declaration tests" (map makeGenTest testDecls)
+             , testGroup "module tests" (map makeGenTest testModules)
+             ]
+
+makeGenTest :: SourceInfoTraversal elem => (String, String, Ann elem dom SrcTemplateStage) -> TestTree
+makeGenTest (name, expected, ast) = testCase name $ assertEqual "The generated AST is not what is expected" expected (prettyPrint ast)
+
+testBase
+  = [ makeGenTest ("qualified name", "A.b", mkNormalName $ mkQualifiedName ["A"] "b")
+    , makeGenTest ("qualified operator", "A.+", mkQualOp ["A"] "+")
+    , makeGenTest ("backtick operator", "`mod`", mkBacktickOp [] "mod")
+    , makeGenTest ("operator name", "(+)", mkParenName $ mkSimpleName "+")
+    ]
+
+testExprs 
+  = [ ("infix", "a + 3", mkInfixApp (mkVar (mkName "a")) (mkUnqualOp "+") (mkLit $ mkIntLit 3)) 
+    , ("section", "(\"xx\"++)", mkLeftSection (mkLit (mkStringLit "xx")) (mkUnqualOp "++"))
+    , ("tuple", "(1, [2, 3])", mkTuple [ mkLit (mkIntLit 1), mkList [ mkLit (mkIntLit 2), mkLit (mkIntLit 3) ] ])
+    , ("record constructor", "P { x = 1 }", mkRecCon (mkName "P") [ mkFieldUpdate (mkName "x") (mkLit $ mkIntLit 1) ])
+    , ("if", "if f a then x else y"
+      , mkIf (mkApp (mkVar $ mkName "f") (mkVar $ mkName "a")) (mkVar $ mkName "x") (mkVar $ mkName "y"))
+    , ("let", "let nat = [0..] in !z"
+      , mkLet [mkLocalValBind $ mkSimpleBind' (mkName "nat") (mkEnum (mkLit (mkIntLit 0)) Nothing Nothing)] 
+                                              (mkPrefixApp (mkUnqualOp "!") (mkVar $ mkName "z")) )
+    , ("case",   "case x of Just y -> y\n"
+              ++ "          Nothing -> 0"
+      , mkCase (mkVar (mkName "x")) 
+          [ mkAlt (mkAppPat (mkName "Just") [mkVarPat (mkName "y")]) (mkCaseRhs $ mkVar (mkName "y")) Nothing
+          , mkAlt (mkVarPat $ mkName "Nothing") (mkCaseRhs $ mkLit $ mkIntLit 0) Nothing
+          ])
+    , ("multiway if",   "if | x > y -> x\n"
+                     ++ "   | otherwise -> y"
+      , mkMultiIf [ mkGuardedCaseRhs 
+                     [ mkGuardCheck $ mkInfixApp (mkVar (mkName "x")) (mkUnqualOp ">") (mkVar (mkName "y"))] 
+                     (mkVar (mkName "x"))
+                  , mkGuardedCaseRhs [mkGuardCheck $ mkVar (mkName "otherwise")] (mkVar (mkName "y"))
+                  ])
+    , ("do notation",   "do x <- a\n"
+                     ++ "   return x"
+      , mkDoBlock [ G.mkBindStmt (mkVarPat (mkName "x")) (mkVar (mkName "a"))
+                  , mkExprStmt (mkApp (mkVar $ mkName "return") (mkVar $ mkName "x"))
+                  ])
+    ]
+
+testPatterns
+  = [ ("irrefutable pattern", "~[0, a]", mkIrrefutablePat $ mkListPat [ mkLitPat (mkIntLit 0), mkVarPat (mkName "a") ])
+    , ("named pattern", "p@Point{ x = 1 }"
+      , mkAsPat (mkName "p") $ mkRecPat (mkName "Point") 
+                                 [ mkPatternField (mkName "x") (mkLitPat (mkIntLit 1)) ])
+    , ("bang pattern", "!(_, f -> 3)"
+      , mkBangPat $ mkTuplePat [mkWildPat, mkViewPat (mkVar $ mkName "f") (mkLitPat (mkIntLit 3))])
+    ]
+
+testType
+  = [ ("forall type", "forall x . Eq x => x -> ()"
+      , mkForallType [mkTypeVar (mkName "x")] 
+          $ mkCtxType (mkContextOne (mkClassAssert (mkName "Eq") [mkVarType (mkName "x")])) 
+          $ mkFunctionType (mkVarType (mkName "x")) (mkVarType (mkName "()")))
+    , ("type operators", "(A :+: B) (x, x)"
+      , mkTypeApp (mkParenType $ mkInfixTypeApp (mkVarType (mkName "A")) (mkUnqualOp ":+:") (mkVarType (mkName "B")))
+                  (mkTupleType [ mkVarType (mkName "x"), mkVarType (mkName "x") ]))
+    ]
+
+testBinds
+  = [ ("locals",   "x = (a, b) where a = 3\n"
+                ++ "                 b = 4"
+      , mkSimpleBind (mkVarPat (mkName "x")) (mkUnguardedRhs (mkTuple [(mkVar (mkName "a")), (mkVar (mkName "b"))]))
+                     (Just $ mkLocalBinds' [ mkLocalValBind $ mkSimpleBind' (mkName "a") (mkLit $ mkIntLit 3)
+                                           , mkLocalValBind $ mkSimpleBind' (mkName "b") (mkLit $ mkIntLit 4)
+                                           ]) )
+    , ("function bind",   "f i 0 = i\n"
+                       ++ "f i x = x"
+      , mkFunctionBind' (mkName "f") [ ([mkVarPat $ mkName "i", mkLitPat $ mkIntLit 0], mkVar $ mkName "i")
+                                     , ([mkVarPat $ mkName "i", mkVarPat $ mkName "x"], mkVar $ mkName "x")
+                                     ])
+    ]
+
+testDecls
+  = [ ("signature", "id :: a -> a"
+      , mkTypeSigDecl $ mkTypeSignature (mkName "id") (mkFunctionType (mkVarType (mkName "a")) (mkVarType (mkName "a"))))
+    , ("binding", "id x = x"
+      , mkValueBinding $ mkFunctionBind' (mkName "id") [([mkVarPat $ mkName "x"], mkVar $ mkName "x")])
+    , ("datatype definition", "data A a = A a deriving Show"
+      , mkDataDecl mkDataKeyword Nothing (mkDeclHeadApp (mkNameDeclHead (mkName "A")) (mkTypeVar (mkName "a"))) 
+          [mkConDecl (mkName "A") [mkVarType (mkName "a")]] (Just $ mkDeriving [mkInstanceHead (mkName "Show")]))
+    , ("record definition", "data A = A { x :: Int }"
+      , mkDataDecl mkDataKeyword Nothing (mkNameDeclHead (mkName "A")) 
+          [mkRecordConDecl (mkName "A") [mkFieldDecl [mkName "x"] (mkVarType (mkName "Int"))]] Nothing)
+    , ("typeclass definition",    "class A t => C t where f :: t\n"
+                               ++ "                       type T t :: *"
+      , mkClassDecl (Just $ mkContextOne (mkClassAssert (mkName "A") [mkVarType (mkName "t")])) 
+                    (mkDeclHeadApp (mkNameDeclHead (mkName "C")) (mkTypeVar (mkName "t"))) []
+                    (Just $ mkClassBody [ mkClassElemSig $ mkTypeSignature (mkName "f") (mkVarType (mkName "t"))
+                                        , mkClassElemTypeFam (mkDeclHeadApp (mkNameDeclHead (mkName "T")) 
+                                                                            (mkTypeVar (mkName "t"))) 
+                                                             (Just $ mkTypeFamilyKindSpec $ mkKindConstraint $ mkKindStar)
+                                        ])
+      )
+    , ( "instance definition", "instance C Int where f = 0"
+      , mkInstanceDecl Nothing (mkInstanceRule Nothing $ mkAppInstanceHead (mkInstanceHead $ mkName "C") (mkVarType (mkName "Int"))) 
+          (Just $ mkInstanceBody [mkInstanceBind $ mkSimpleBind' (mkName "f") (mkLit $ mkIntLit 0)]))
+    , ("fixity definition", "infixl 6 +", mkFixityDecl $ mkInfixL 6 (mkUnqualOp "+"))
+    ]
+
+testModules
+  = [ ("empty module", "", G.mkModule [] Nothing [] [])
+    , ("exports", "module Test(x, A(a), B(..)) where"
+      , G.mkModule [] (Just $ mkModuleHead (G.mkModuleName "Test") 
+          (Just $ mkExportSpecs 
+                    [ mkExportSpec $ mkIESpec (mkName "x") Nothing
+                    , mkExportSpec $ mkIESpec (mkName "A") (Just $ mkSubList [mkName "a"])
+                    , mkExportSpec $ mkIESpec (mkName "B") (Just mkSubAll)
+                    ]) Nothing) [] [])
+    , ("imports",  "\nimport qualified A\n"
+                  ++ "import B as BB(x)\n"
+                  ++ "import B hiding (x)"
+    , G.mkModule [] Nothing 
+        [ mkImportDecl False True False Nothing (G.mkModuleName "A") Nothing Nothing
+        , mkImportDecl False False False Nothing (G.mkModuleName "B") (Just $ G.mkModuleName "BB") 
+            (Just $ mkImportSpecList [mkIESpec (mkName "x") Nothing])
+        , mkImportDecl False False False Nothing (G.mkModuleName "B") Nothing 
+            (Just $ mkImportHidingList [mkIESpec (mkName "x") Nothing])
+        ] [])
+    ]
