-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Generic representation and manipulation of abstract syntax -- -- The library provides a generic representation of type-indexed abstract -- syntax trees (or indexed data types in general). It also permits the -- definition of open syntax trees based on the technique in Data Types à -- la Carte [1]. -- -- (Note that the difference between version 2.x and 3.0 is not that big. -- The bump to 3.0 was done because the modules changed namespace.) -- -- For more information, see "A Generic Abstract Syntax Model for -- Embedded Languages" (ICFP 2012): -- -- -- -- Example EDSLs can be found in the examples folder. -- -- [1] W. Swierstra. Data Types à la Carte. Journal of Functional -- Programming, 18(4):423-436, 2008, -- http://dx.doi.org/10.1017/S0956796808006758. @package syntactic @version 3.0 -- | Generic representation of typed syntax trees -- -- For details, see: A Generic Abstract Syntax Model for Embedded -- Languages (ICFP 2012, -- http://www.cse.chalmers.se/~emax/documents/axelsson2012generic.pdf). module Language.Syntactic.Syntax -- | Generic abstract syntax tree, parameterized by a symbol domain -- -- (AST sym (a :-> b)) represents a partially -- applied (or unapplied) symbol, missing at least one argument, while -- (AST sym (Full a)) represents a fully applied -- symbol, i.e. a complete syntax tree. data AST sym sig Sym :: sym sig -> AST sym sig (:$) :: AST sym (a :-> sig) -> AST sym (Full a) -> AST sym sig -- | Fully applied abstract syntax tree type ASTF sym a = AST sym (Full a) -- | Signature of a fully applied symbol newtype Full a Full :: a -> Full a [result] :: Full a -> a -- | Signature of a partially applied (or unapplied) symbol newtype (:->) a sig Partial :: (a -> sig) -> (:->) a sig -- | Witness of the arity of a symbol signature data SigRep sig SigFull :: SigRep (Full a) SigMore :: SigRep sig -> SigRep (a :-> sig) -- | Valid symbol signatures class Signature sig signature :: Signature sig => SigRep sig -- | The result type of a symbol with the given signature -- | Valid symbols to use in an AST class Symbol sym where rnfSym s = s `seq` () -- | Force a symbol to normal form rnfSym :: Symbol sym => sym sig -> () -- | Reify the signature of a symbol symSig :: Symbol sym => sym sig -> SigRep sig -- | Count the number of symbols in an AST size :: AST sym sig -> Int -- | Maps a symbol signature to the type of the corresponding smart -- constructor: -- --
--   SmartFun sym (a :-> b :-> ... :-> Full x) = ASTF sym a -> ASTF sym b -> ... -> ASTF sym x
--   
-- | Maps a smart constructor type to the corresponding symbol signature: -- --
--   SmartSig (ASTF sym a -> ASTF sym b -> ... -> ASTF sym x) = a :-> b :-> ... :-> Full x
--   
-- | Returns the symbol in the result of a smart constructor -- | Make a smart constructor of a symbol. smartSym has any type of -- the form: -- --
--   smartSym
--       :: sym (a :-> b :-> ... :-> Full x)
--       -> (ASTF sym a -> ASTF sym b -> ... -> ASTF sym x)
--   
smartSym' :: (Signature sig, f ~ SmartFun sym sig, sig ~ SmartSig f, sym ~ SmartSym f) => sym sig -> f -- | Direct sum of two symbol domains data (:+:) sym1 sym2 sig InjL :: sym1 a -> (sym1 :+: sym2) a InjR :: sym2 a -> (sym1 :+: sym2) a -- | Symbol projection -- -- The class is defined for all pairs of types, but prj can -- only succeed if sup is of the form (... :+: sub -- :+: ...). class Project sub sup -- | Partial projection from sup to sub prj :: Project sub sup => sup a -> Maybe (sub a) -- | Symbol injection -- -- The class includes types sub and sup where -- sup is of the form (... :+: sub :+: -- ...). class Project sub sup => (:<:) sub sup -- | Injection from sub to sup inj :: (:<:) sub sup => sub a -> sup a -- | Make a smart constructor of a symbol. smartSym has any type of -- the form: -- --
--   smartSym :: (sub :<: AST sup)
--       => sub (a :-> b :-> ... :-> Full x)
--       -> (ASTF sup a -> ASTF sup b -> ... -> ASTF sup x)
--   
smartSym :: (Signature sig, f ~ SmartFun sup sig, sig ~ SmartSig f, sup ~ SmartSym f, sub :<: sup) => sub sig -> f -- | Make a smart constructor of a symbol. smartSymT has any type of -- the form: -- --
--   smartSym :: (sub :<: AST (Typed sup), Typeable x)
--       => sub (a :-> b :-> ... :-> Full x)
--       -> (ASTF sup a -> ASTF sup b -> ... -> ASTF sup x)
--   
smartSymT :: (Signature sig, f ~ SmartFun (Typed sup) sig, sig ~ SmartSig f, Typed sup ~ SmartSym f, sub :<: sup, Typeable (DenResult sig)) => sub sig -> f -- | Empty symbol type -- -- Can be used to make uninhabited AST types. It can also be used -- as a terminator in co-product lists (e.g. to avoid overlapping -- instances): -- --
--   (A :+: B :+: Empty)
--   
data Empty :: * -> * -- | Existential quantification data E e E :: e a -> E e liftE :: (forall a. e a -> b) -> E e -> b liftE2 :: (forall a b. e a -> e b -> c) -> E e -> E e -> c -- | Existential quantification of Full-indexed type data EF e EF :: e (Full a) -> EF e liftEF :: (forall a. e (Full a) -> b) -> EF e -> b liftEF2 :: (forall a b. e (Full a) -> e (Full b) -> c) -> EF e -> EF e -> c -- | "Typed" symbol. Using Typed sym instead of -- sym gives access to the function castExpr for casting -- expressions. data Typed sym sig Typed :: sym sig -> Typed sym sig -- | Inject a symbol in an AST with a Typed domain injT :: (sub :<: sup, Typeable (DenResult sig)) => sub sig -> AST (Typed sup) sig -- | Type cast an expression castExpr :: ASTF (Typed sym) a -> ASTF (Typed sym) b -> Maybe (ASTF (Typed sym) b) -- | Constrain a symbol to a specific type symType :: Proxy sym -> sym sig -> sym sig -- | Projection to a specific symbol type prjP :: Project sub sup => Proxy sub -> sup sig -> Maybe (sub sig) instance (Data.Traversable.Traversable sym1, Data.Traversable.Traversable sym2) => Data.Traversable.Traversable (sym1 Language.Syntactic.Syntax.:+: sym2) instance (Data.Foldable.Foldable sym1, Data.Foldable.Foldable sym2) => Data.Foldable.Foldable (sym1 Language.Syntactic.Syntax.:+: sym2) instance (GHC.Base.Functor sym1, GHC.Base.Functor sym2) => GHC.Base.Functor (sym1 Language.Syntactic.Syntax.:+: sym2) instance GHC.Base.Functor ((Language.Syntactic.Syntax.:->) a) instance GHC.Base.Functor Language.Syntactic.Syntax.Full instance GHC.Show.Show a => GHC.Show.Show (Language.Syntactic.Syntax.Full a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Syntactic.Syntax.Full a) instance GHC.Base.Functor sym => GHC.Base.Functor (Language.Syntactic.Syntax.AST sym) instance Language.Syntactic.Syntax.Signature (Language.Syntactic.Syntax.Full a) instance Language.Syntactic.Syntax.Signature sig => Language.Syntactic.Syntax.Signature (a Language.Syntactic.Syntax.:-> sig) instance Language.Syntactic.Syntax.Symbol sym => Control.DeepSeq.NFData (Language.Syntactic.Syntax.AST sym sig) instance (Language.Syntactic.Syntax.Symbol sym1, Language.Syntactic.Syntax.Symbol sym2) => Language.Syntactic.Syntax.Symbol (sym1 Language.Syntactic.Syntax.:+: sym2) instance Language.Syntactic.Syntax.Project sub sup => Language.Syntactic.Syntax.Project sub (Language.Syntactic.Syntax.AST sup) instance Language.Syntactic.Syntax.Project sym sym instance Language.Syntactic.Syntax.Project sym1 (sym1 Language.Syntactic.Syntax.:+: sym2) instance Language.Syntactic.Syntax.Project sym1 sym3 => Language.Syntactic.Syntax.Project sym1 (sym2 Language.Syntactic.Syntax.:+: sym3) instance Language.Syntactic.Syntax.Project sub sup instance (sub Language.Syntactic.Syntax.:<: sup) => sub Language.Syntactic.Syntax.:<: Language.Syntactic.Syntax.AST sup instance sym Language.Syntactic.Syntax.:<: sym instance sym1 Language.Syntactic.Syntax.:<: (sym1 Language.Syntactic.Syntax.:+: sym2) instance (sym1 Language.Syntactic.Syntax.:<: sym3) => sym1 Language.Syntactic.Syntax.:<: (sym2 Language.Syntactic.Syntax.:+: sym3) instance Language.Syntactic.Syntax.Project sub sup => Language.Syntactic.Syntax.Project sub (Language.Syntactic.Syntax.Typed sup) -- | Generic traversals of AST terms module Language.Syntactic.Traversal -- | Map a function over all immediate sub-terms, collecting the results in -- a list (corresponds to the function with the same name in Scrap Your -- Boilerplate) gmapQ :: (forall a. ASTF sym a -> b) -> (forall a. ASTF sym a -> [b]) -- | Map a function over all immediate sub-terms (corresponds to the -- function with the same name in Scrap Your Boilerplate) gmapT :: (forall a. ASTF sym a -> ASTF sym a) -> (forall a. ASTF sym a -> ASTF sym a) -- | Apply a transformation bottom-up over an AST (corresponds to -- everywhere in Scrap Your Boilerplate) everywhereUp :: (forall a. ASTF sym a -> ASTF sym a) -> (forall a. ASTF sym a -> ASTF sym a) -- | Apply a transformation top-down over an AST (corresponds to -- everywhere' in Scrap Your Boilerplate) everywhereDown :: (forall a. ASTF sym a -> ASTF sym a) -> (forall a. ASTF sym a -> ASTF sym a) -- | List all sub-terms (corresponds to universe in Uniplate) universe :: ASTF sym a -> [EF (AST sym)] -- | List of symbol arguments data Args c sig Nil :: Args c (Full a) (:*) :: c (Full a) -> Args c sig -> Args c (a :-> sig) -- | Map a function over an Args list and collect the results in an -- ordinary list listArgs :: (forall a. c (Full a) -> b) -> Args c sig -> [b] -- | Map a function over an Args list mapArgs :: (forall a. c1 (Full a) -> c2 (Full a)) -> (forall sig. Args c1 sig -> Args c2 sig) -- | Map an applicative function over an Args list mapArgsA :: Applicative f => (forall a. c1 (Full a) -> f (c2 (Full a))) -> (forall sig. Args c1 sig -> f (Args c2 sig)) -- | Map a monadic function over an Args list mapArgsM :: Monad m => (forall a. c1 (Full a) -> m (c2 (Full a))) -> (forall sig. Args c1 sig -> m (Args c2 sig)) -- | Right fold for an Args list foldrArgs :: (forall a. c (Full a) -> b -> b) -> b -> (forall sig. Args c sig -> b) -- | Apply a (partially applied) symbol to a list of argument terms appArgs :: AST sym sig -> Args (AST sym) sig -> ASTF sym (DenResult sig) -- | Fold an AST using a list to hold the results of sub-terms listFold :: (forall sig. sym sig -> [b] -> b) -> (forall a. ASTF sym a -> b) -- | "Pattern match" on an AST using a function that gets direct -- access to the top-most symbol and its sub-trees match :: (forall sig. (a ~ DenResult sig) => sym sig -> Args (AST sym) sig -> c (Full a)) -> ASTF sym a -> c (Full a) -- | A version of match with a simpler result type simpleMatch :: (forall sig. (a ~ DenResult sig) => sym sig -> Args (AST sym) sig -> b) -> ASTF sym a -> b -- | Fold an AST using an Args list to hold the results of -- sub-terms fold :: (forall sig. sym sig -> Args c sig -> c (Full (DenResult sig))) -> (forall a. ASTF sym a -> c (Full a)) -- | Simplified version of fold for situations where all -- intermediate results have the same type simpleFold :: (forall sig. sym sig -> Args (Const b) sig -> b) -> (forall a. ASTF sym a -> b) -- | A version of match where the result is a transformed syntax -- tree, wrapped in a type constructor c matchTrans :: (forall sig. (a ~ DenResult sig) => sym sig -> Args (AST sym) sig -> c (ASTF sym' a)) -> ASTF sym a -> c (ASTF sym' a) -- | Update the symbols in an AST mapAST :: (forall sig'. sym1 sig' -> sym2 sig') -> AST sym1 sig -> AST sym2 sig -- | Can be used to make an arbitrary type constructor indexed by -- (Full a). This is useful as the type constructor -- parameter of Args. That is, use -- --
--   Args (WrapFull c) ...
--   
-- -- instead of -- --
--   Args c ...
--   
-- -- if c is not indexed by (Full a). data WrapFull c a WrapFull :: c a -> WrapFull c (Full a) [unwrapFull] :: WrapFull c (Full a) -> c a -- | Convert an AST to a Tree toTree :: (forall sig. dom sig -> b) -> ASTF dom a -> Tree b -- | Equality and rendering of ASTs module Language.Syntactic.Interpretation -- | Higher-kinded equality class Equality e -- | Higher-kinded equality -- -- Comparing elements of different types is often needed when dealing -- with expressions with existentially quantified sub-terms. equal :: Equality e => e a -> e b -> Bool -- | Higher-kinded hashing. Elements that are equal according to -- equal must result in the same hash: -- --
--   equal a b  ==>  hash a == hash b
--   
hash :: Equality e => e a -> Hash -- | Render a symbol as concrete syntax. A complete instance must define at -- least the renderSym method. class Render sym where renderArgs [] s = renderSym s renderArgs args s = "(" ++ unwords (renderSym s : args) ++ ")" -- | Show a symbol as a String renderSym :: Render sym => sym sig -> String -- | Render a symbol given a list of rendered arguments renderArgs :: Render sym => [String] -> sym sig -> String -- | Implementation of renderArgs that handles infix operators renderArgsSmart :: Render sym => [String] -> sym a -> String -- | Render an AST as concrete syntax render :: Render sym => ASTF sym a -> String -- | Convert a symbol to a Tree of strings class Render sym => StringTree sym where stringTreeSym args s = Node (renderSym s) args -- | Convert a symbol to a Tree given a list of argument trees stringTreeSym :: StringTree sym => [Tree String] -> sym a -> Tree String -- | Convert an AST to a Tree of strings stringTree :: StringTree sym => ASTF sym a -> Tree String -- | Show a syntax tree using ASCII art showAST :: StringTree sym => ASTF sym a -> String -- | Print a syntax tree using ASCII art drawAST :: StringTree sym => ASTF sym a -> IO () -- | Write a syntax tree to an HTML file with foldable nodes writeHtmlAST :: StringTree sym => FilePath -> ASTF sym a -> IO () -- | Default implementation of equal equalDefault :: Render sym => sym a -> sym b -> Bool -- | Default implementation of hash hashDefault :: Render sym => sym a -> Hash -- | Derive instances for Equality and StringTree interpretationInstances :: Name -> DecsQ instance Language.Syntactic.Interpretation.Equality sym => Language.Syntactic.Interpretation.Equality (Language.Syntactic.Syntax.AST sym) instance Language.Syntactic.Interpretation.Equality sym => GHC.Classes.Eq (Language.Syntactic.Syntax.AST sym a) instance (Language.Syntactic.Interpretation.Equality sym1, Language.Syntactic.Interpretation.Equality sym2) => Language.Syntactic.Interpretation.Equality (sym1 Language.Syntactic.Syntax.:+: sym2) instance (Language.Syntactic.Interpretation.Equality sym1, Language.Syntactic.Interpretation.Equality sym2) => GHC.Classes.Eq ((Language.Syntactic.Syntax.:+:) sym1 sym2 a) instance Language.Syntactic.Interpretation.Equality Language.Syntactic.Syntax.Empty instance Language.Syntactic.Interpretation.Equality sym => Language.Syntactic.Interpretation.Equality (Language.Syntactic.Syntax.Typed sym) instance (Language.Syntactic.Interpretation.Render sym1, Language.Syntactic.Interpretation.Render sym2) => Language.Syntactic.Interpretation.Render (sym1 Language.Syntactic.Syntax.:+: sym2) instance Language.Syntactic.Interpretation.Render Language.Syntactic.Syntax.Empty instance Language.Syntactic.Interpretation.Render sym => Language.Syntactic.Interpretation.Render (Language.Syntactic.Syntax.Typed sym) instance Language.Syntactic.Interpretation.Render sym => GHC.Show.Show (Language.Syntactic.Syntax.ASTF sym a) instance (Language.Syntactic.Interpretation.StringTree sym1, Language.Syntactic.Interpretation.StringTree sym2) => Language.Syntactic.Interpretation.StringTree (sym1 Language.Syntactic.Syntax.:+: sym2) instance Language.Syntactic.Interpretation.StringTree Language.Syntactic.Syntax.Empty instance Language.Syntactic.Interpretation.StringTree sym => Language.Syntactic.Interpretation.StringTree (Language.Syntactic.Syntax.Typed sym) -- | "Syntactic sugar" -- -- For details, see "Combining Deep and Shallow Embedding for EDSL" (TFP -- 2013, -- http://www.cse.chalmers.se/~emax/documents/svenningsson2013combining.pdf). module Language.Syntactic.Sugar -- | It is usually assumed that (desugar (sugar a)) -- has the same meaning as a. class Syntactic a where type family Domain a :: * -> * type family Internal a desugar :: Syntactic a => a -> ASTF (Domain a) (Internal a) sugar :: Syntactic a => ASTF (Domain a) (Internal a) -> a -- | Syntactic type casting resugar :: (Syntactic a, Syntactic b, Domain a ~ Domain b, Internal a ~ Internal b) => a -> b -- | N-ary syntactic functions -- -- desugarN has any type of the form: -- --
--   desugarN ::
--       ( Syntactic a
--       , Syntactic b
--       , ...
--       , Syntactic x
--       , Domain a ~ sym
--       , Domain b ~ sym
--       , ...
--       , Domain x ~ sym
--       ) => (a -> b -> ... -> x)
--         -> (  ASTF sym (Internal a)
--            -> ASTF sym (Internal b)
--            -> ...
--            -> ASTF sym (Internal x)
--            )
--   
-- -- ...and vice versa for sugarN. class SyntacticN f internal | f -> internal desugarN :: SyntacticN f internal => f -> internal sugarN :: SyntacticN f internal => internal -> f -- | "Sugared" symbol application -- -- sugarSym has any type of the form: -- --
--   sugarSym ::
--       ( sub :<: AST sup
--       , Syntactic a
--       , Syntactic b
--       , ...
--       , Syntactic x
--       , Domain a ~ Domain b ~ ... ~ Domain x
--       ) => sub (Internal a :-> Internal b :-> ... :-> Full (Internal x))
--         -> (a -> b -> ... -> x)
--   
sugarSym :: (Signature sig, fi ~ SmartFun sup sig, sig ~ SmartSig fi, sup ~ SmartSym fi, SyntacticN f fi, sub :<: sup) => sub sig -> f -- | "Sugared" symbol application -- -- sugarSym has any type of the form: -- --
--   sugarSym ::
--       ( sub :<: AST (Typed sup)
--       , Syntactic a
--       , Syntactic b
--       , ...
--       , Syntactic x
--       , Domain a ~ Domain b ~ ... ~ Domain x
--       , Typeable (Internal x)
--       ) => sub (Internal a :-> Internal b :-> ... :-> Full (Internal x))
--         -> (a -> b -> ... -> x)
--   
sugarSymT :: (Signature sig, fi ~ SmartFun (Typed sup) sig, sig ~ SmartSig fi, Typed sup ~ SmartSym fi, SyntacticN f fi, sub :<: sup, Typeable (DenResult sig)) => sub sig -> f instance Language.Syntactic.Sugar.Syntactic (Language.Syntactic.Syntax.ASTF sym a) instance (Language.Syntactic.Sugar.Syntactic f, Language.Syntactic.Sugar.Domain f ~ sym, fi ~ Language.Syntactic.Syntax.AST sym (Language.Syntactic.Syntax.Full (Language.Syntactic.Sugar.Internal f))) => Language.Syntactic.Sugar.SyntacticN f fi instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Domain a ~ sym, ia ~ Language.Syntactic.Sugar.Internal a, Language.Syntactic.Sugar.SyntacticN f fi) => Language.Syntactic.Sugar.SyntacticN (a -> f) (Language.Syntactic.Syntax.AST sym (Language.Syntactic.Syntax.Full ia) -> fi) -- | Construct for decorating symbols or expressions with additional -- information module Language.Syntactic.Decoration -- | Decorating symbols or expressions with additional information -- -- One usage of :&: is to decorate every node of a syntax -- tree. This is done simply by changing -- --
--   AST sym sig
--   
-- -- to -- --
--   AST (sym :&: info) sig
--   
data (:&:) expr info sig (:&:) :: expr sig -> info (DenResult sig) -> (expr :&: info) sig [decorExpr] :: (expr :&: info) sig -> expr sig [decorInfo] :: (expr :&: info) sig -> info (DenResult sig) -- | Map over a decoration mapDecor :: (sym1 sig -> sym2 sig) -> (info1 (DenResult sig) -> info2 (DenResult sig)) -> ((sym1 :&: info1) sig -> (sym2 :&: info2) sig) -- | Get the decoration of the top-level node getDecor :: AST (sym :&: info) sig -> info (DenResult sig) -- | Update the decoration of the top-level node updateDecor :: (info a -> info a) -> ASTF (sym :&: info) a -> ASTF (sym :&: info) a -- | Lift a function that operates on expressions with associated -- information to operate on a :&: expression. This function -- is convenient to use together with e.g. queryNodeSimple when -- the domain has the form (sym :&: info). liftDecor :: (expr s -> info (DenResult s) -> b) -> ((expr :&: info) s -> b) -- | Strip decorations from an AST stripDecor :: AST (sym :&: info) sig -> AST sym sig -- | Rendering of decorated syntax trees stringTreeDecor :: StringTree sym => (forall a. info a -> String) -> ASTF (sym :&: info) a -> Tree String -- | Show an decorated syntax tree using ASCII art showDecorWith :: StringTree sym => (forall a. info a -> String) -> ASTF (sym :&: info) a -> String -- | Print an decorated syntax tree using ASCII art drawDecorWith :: StringTree sym => (forall a. info a -> String) -> ASTF (sym :&: info) a -> IO () writeHtmlDecorWith :: (StringTree sym) => (forall b. info b -> String) -> FilePath -> ASTF (sym :&: info) a -> IO () instance Language.Syntactic.Syntax.Symbol sym => Language.Syntactic.Syntax.Symbol (sym Language.Syntactic.Decoration.:&: info) instance Language.Syntactic.Syntax.Project sub sup => Language.Syntactic.Syntax.Project sub (sup Language.Syntactic.Decoration.:&: info) instance Language.Syntactic.Interpretation.Equality expr => Language.Syntactic.Interpretation.Equality (expr Language.Syntactic.Decoration.:&: info) instance Language.Syntactic.Interpretation.Render expr => Language.Syntactic.Interpretation.Render (expr Language.Syntactic.Decoration.:&: info) instance Language.Syntactic.Interpretation.StringTree expr => Language.Syntactic.Interpretation.StringTree (expr Language.Syntactic.Decoration.:&: info) -- | The basic parts of the syntactic library module Language.Syntactic -- | Basics for implementing functional EDSLs module Language.Syntactic.Functional -- | Variable name newtype Name Name :: Integer -> Name -- | Generic N-ary syntactic construct -- -- Construct gives a quick way to introduce a syntactic construct -- by giving its name and semantic function. data Construct sig Construct :: String -> Denotation sig -> Construct sig -- | Variables and binders data Binding sig Var :: Name -> Binding (Full a) Lam :: Name -> Binding (b :-> Full (a -> b)) -- | Get the highest name bound by the first Lam binders at every -- path from the root. If the term has ordered binders [1], -- maxLam returns the highest name introduced in the whole term. -- -- [1] Ordered binders means that the names of Lam nodes are -- decreasing along every path from the root. maxLam :: (Binding :<: s) => AST s a -> Name -- | Higher-order interface for variable binding -- -- Assumptions: -- -- -- -- [1] Ordered binders means that the names of Lam nodes are -- decreasing along every path from the root. -- -- See "Using Circular Programs for Higher-Order Syntax" (ICFP 2013, -- http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf). lam :: (Binding :<: s) => (ASTF s a -> ASTF s b) -> ASTF s (a -> b) -- | Convert from a term with De Bruijn indexes to one with explicit names -- -- In the argument term, variable Names are treated as De Bruijn -- indexes, and lambda Names are ignored. (Ideally, one should use -- a different type for De Bruijn terms.) fromDeBruijn :: (Binding :<: sym) => ASTF sym a -> ASTF sym a -- | Typed variables and binders data BindingT sig VarT :: Name -> BindingT (Full a) LamT :: Name -> BindingT (b :-> Full (a -> b)) -- | Get the highest name bound by the first LamT binders at every -- path from the root. If the term has ordered binders [1], -- maxLamT returns the highest name introduced in the whole term. -- -- [1] Ordered binders means that the names of LamT nodes are -- decreasing along every path from the root. maxLamT :: Project BindingT sym => AST sym a -> Name -- | Higher-order interface for typed variable binding -- -- Assumptions: -- -- -- -- [1] Ordered binders means that the names of LamT nodes are -- decreasing along every path from the root. -- -- See "Using Circular Programs for Higher-Order Syntax" (ICFP 2013, -- http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf). lamT :: (BindingT :<: sym, symT ~ Typed sym, Typeable a, Typeable b) => (ASTF symT a -> ASTF symT b) -> ASTF symT (a -> b) -- | Domains that "might" include variables and binders class BindingDomain sym prVar :: BindingDomain sym => sym sig -> Maybe Name prLam :: BindingDomain sym => sym sig -> Maybe Name -- | A symbol for let bindings -- -- This symbol is just an application operator. The actual binding has to -- be done by a lambda that constructs the second argument. data Let sig Let :: Let (a :-> ((a -> b) :-> Full b)) -- | Monadic constructs -- -- See "Generic Monadic Constructs for Embedded Languages" (Persson et -- al., IFL 2011 -- http://www.cse.chalmers.se/~emax/documents/persson2011generic.pdf). data MONAD m sig Return :: MONAD m (a :-> Full (m a)) Bind :: MONAD m (m a :-> ((a -> m b) :-> Full (m b))) -- | Reifiable monad -- -- See "Generic Monadic Constructs for Embedded Languages" (Persson et -- al., IFL 2011 -- http://www.cse.chalmers.se/~emax/documents/persson2011generic.pdf). -- -- It is advised to convert to/from Remon using the -- Syntactic instance provided in the modules -- Language.Syntactic.Sugar.Monad or -- Language.Syntactic.Sugar.MonadT. newtype Remon sym m a Remon :: (forall r. Typeable r => Cont (ASTF sym (m r)) a) -> Remon sym m a [unRemon] :: Remon sym m a -> forall r. Typeable r => Cont (ASTF sym (m r)) a -- | One-layer desugaring of monadic actions desugarMonad :: (MONAD m :<: sym, Typeable a, Typeable m) => Remon sym m (ASTF sym a) -> ASTF sym (m a) -- | One-layer desugaring of monadic actions desugarMonadT :: (MONAD m :<: sym, symT ~ Typed sym, Typeable a, Typeable m) => Remon symT m (ASTF symT a) -> ASTF symT (m a) -- | Get the set of free variables in an expression freeVars :: BindingDomain sym => AST sym sig -> Set Name -- | Get the set of variables (free, bound and introduced by lambdas) in an -- expression allVars :: BindingDomain sym => AST sym sig -> Set Name -- | Environment used by alphaEq' type AlphaEnv = [(Name, Name)] alphaEq' :: (Equality sym, BindingDomain sym) => AlphaEnv -> ASTF sym a -> ASTF sym b -> Bool -- | Alpha-equivalence alphaEq :: (Equality sym, BindingDomain sym) => ASTF sym a -> ASTF sym b -> Bool -- | Semantic function type of the given symbol signature class Eval s evalSym :: Eval s => s sig -> Denotation sig -- | Evaluation evalDen :: Eval s => AST s sig -> Denotation sig -- | Monadic denotation; mapping from a symbol signature -- --
--   a :-> b :-> Full c
--   
-- -- to -- --
--   m a -> m b -> m c
--   
-- | Lift a Denotation to DenotationM liftDenotationM :: Monad m => SigRep sig -> proxy1 m -> proxy2 sig -> Denotation sig -> DenotationM m sig -- | Runtime environment type RunEnv = [(Name, Dynamic)] -- | Evaluation class EvalEnv sym env where compileSym p s = compileSymDefault (symSig s) p s compileSym :: EvalEnv sym env => proxy env -> sym sig -> DenotationM (Reader env) sig -- | Simple implementation of compileSym from a Denotation compileSymDefault :: Eval sym => SigRep sig -> proxy env -> sym sig -> DenotationM (Reader env) sig -- | Evaluation of open terms evalOpen :: EvalEnv sym env => env -> ASTF sym a -> a -- | Evaluation of closed terms where RunEnv is used as the internal -- environment -- -- (Note that there is no guarantee that the term is actually closed.) evalClosed :: EvalEnv sym RunEnv => ASTF sym a -> a instance GHC.Base.Functor (Language.Syntactic.Functional.Remon sym m) instance Control.DeepSeq.NFData Language.Syntactic.Functional.Name instance GHC.Real.Integral Language.Syntactic.Functional.Name instance GHC.Real.Real Language.Syntactic.Functional.Name instance GHC.Enum.Enum Language.Syntactic.Functional.Name instance GHC.Num.Num Language.Syntactic.Functional.Name instance GHC.Classes.Ord Language.Syntactic.Functional.Name instance GHC.Classes.Eq Language.Syntactic.Functional.Name instance Language.Syntactic.Syntax.Symbol Language.Syntactic.Functional.Construct instance Language.Syntactic.Interpretation.Render Language.Syntactic.Functional.Construct instance Language.Syntactic.Interpretation.Equality Language.Syntactic.Functional.Construct instance Language.Syntactic.Interpretation.StringTree Language.Syntactic.Functional.Construct instance GHC.Show.Show Language.Syntactic.Functional.Name instance Language.Syntactic.Syntax.Symbol Language.Syntactic.Functional.Binding instance Language.Syntactic.Interpretation.Equality Language.Syntactic.Functional.Binding instance Language.Syntactic.Interpretation.Render Language.Syntactic.Functional.Binding instance Language.Syntactic.Interpretation.StringTree Language.Syntactic.Functional.Binding instance Language.Syntactic.Syntax.Symbol Language.Syntactic.Functional.BindingT instance Language.Syntactic.Interpretation.Equality Language.Syntactic.Functional.BindingT instance Language.Syntactic.Interpretation.Render Language.Syntactic.Functional.BindingT instance Language.Syntactic.Interpretation.StringTree Language.Syntactic.Functional.BindingT instance (Language.Syntactic.Functional.BindingDomain sym1, Language.Syntactic.Functional.BindingDomain sym2) => Language.Syntactic.Functional.BindingDomain (sym1 Language.Syntactic.Syntax.:+: sym2) instance Language.Syntactic.Functional.BindingDomain sym => Language.Syntactic.Functional.BindingDomain (Language.Syntactic.Syntax.Typed sym) instance Language.Syntactic.Functional.BindingDomain sym => Language.Syntactic.Functional.BindingDomain (sym Language.Syntactic.Decoration.:&: i) instance Language.Syntactic.Functional.BindingDomain sym => Language.Syntactic.Functional.BindingDomain (Language.Syntactic.Syntax.AST sym) instance Language.Syntactic.Functional.BindingDomain Language.Syntactic.Functional.Binding instance Language.Syntactic.Functional.BindingDomain Language.Syntactic.Functional.BindingT instance Language.Syntactic.Functional.BindingDomain sym instance Language.Syntactic.Syntax.Symbol Language.Syntactic.Functional.Let instance Language.Syntactic.Interpretation.Render Language.Syntactic.Functional.Let instance Language.Syntactic.Functional.Eval Language.Syntactic.Functional.Let instance Language.Syntactic.Functional.EvalEnv Language.Syntactic.Functional.Let env instance Language.Syntactic.Interpretation.Equality Language.Syntactic.Functional.Let instance Language.Syntactic.Interpretation.StringTree Language.Syntactic.Functional.Let instance Language.Syntactic.Syntax.Symbol (Language.Syntactic.Functional.MONAD m) instance Language.Syntactic.Interpretation.Render (Language.Syntactic.Functional.MONAD m) instance Language.Syntactic.Interpretation.Equality (Language.Syntactic.Functional.MONAD m) instance Language.Syntactic.Interpretation.StringTree (Language.Syntactic.Functional.MONAD m) instance GHC.Base.Applicative (Language.Syntactic.Functional.Remon sym m) instance GHC.Base.Monad (Language.Syntactic.Functional.Remon dom m) instance (Language.Syntactic.Functional.Eval s, Language.Syntactic.Functional.Eval t) => Language.Syntactic.Functional.Eval (s Language.Syntactic.Syntax.:+: t) instance Language.Syntactic.Functional.Eval Language.Syntactic.Syntax.Empty instance Language.Syntactic.Functional.Eval sym => Language.Syntactic.Functional.Eval (sym Language.Syntactic.Decoration.:&: info) instance Language.Syntactic.Functional.Eval Language.Syntactic.Functional.Construct instance GHC.Base.Monad m => Language.Syntactic.Functional.Eval (Language.Syntactic.Functional.MONAD m) instance (Language.Syntactic.Functional.EvalEnv sym1 env, Language.Syntactic.Functional.EvalEnv sym2 env) => Language.Syntactic.Functional.EvalEnv (sym1 Language.Syntactic.Syntax.:+: sym2) env instance Language.Syntactic.Functional.EvalEnv Language.Syntactic.Syntax.Empty env instance Language.Syntactic.Functional.EvalEnv sym env => Language.Syntactic.Functional.EvalEnv (Language.Syntactic.Syntax.Typed sym) env instance Language.Syntactic.Functional.EvalEnv sym env => Language.Syntactic.Functional.EvalEnv (sym Language.Syntactic.Decoration.:&: info) env instance Language.Syntactic.Functional.EvalEnv Language.Syntactic.Functional.Construct env instance GHC.Base.Monad m => Language.Syntactic.Functional.EvalEnv (Language.Syntactic.Functional.MONAD m) env instance Language.Syntactic.Functional.EvalEnv Language.Syntactic.Functional.BindingT Language.Syntactic.Functional.RunEnv -- | Simple code motion transformation performing common sub-expression -- elimination and variable hoisting. Note that the implementation is -- very inefficient. -- -- The code is based on an implementation by Gergely Dévai. module Language.Syntactic.Functional.Sharing -- | Interface for injecting binding constructs data InjDict sym a b InjDict :: (Name -> sym (Full a)) -> (Name -> sym (b :-> Full (a -> b))) -> sym (a :-> ((a -> b) :-> Full b)) -> InjDict sym a b -- | Inject a variable [injVariable] :: InjDict sym a b -> Name -> sym (Full a) -- | Inject a lambda [injLambda] :: InjDict sym a b -> Name -> sym (b :-> Full (a -> b)) -- | Inject a "let" symbol [injLet] :: InjDict sym a b -> sym (a :-> ((a -> b) :-> Full b)) -- | Code motion interface data CodeMotionInterface sym Interface :: (forall a b. ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b)) -> (forall a b. ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b)) -> (forall c. ASTF sym c -> Bool) -> CodeMotionInterface sym -- | Try to construct an InjDict. The first argument is the -- expression to be shared, and the second argument the expression in -- which it will be shared. This function can be used to transfer -- information (e.g. from static analysis) from the shared expression to -- the introduced variable. [mkInjDict] :: CodeMotionInterface sym -> forall a b. ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b) -- | Try to type cast an expression. The first argument is the expression -- to cast. The second argument can be used to construct a witness to -- support the casting. The resulting expression (if any) should be equal -- to the first argument. [castExprCM] :: CodeMotionInterface sym -> forall a b. ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b) -- | Whether a sub-expression can be hoisted over the given expression [hoistOver] :: CodeMotionInterface sym -> forall c. ASTF sym c -> Bool -- | Default CodeMotionInterface for domains of the form -- Typed (... :+: Binding :+: ...). defaultInterface :: (Binding :<: sym, Let :<: sym, symT ~ Typed sym) => (forall a b. ASTF symT a -> ASTF symT b -> Bool) -> (forall a. ASTF symT a -> Bool) -> CodeMotionInterface symT -- | Default CodeMotionInterface for domains of the form -- Typed (... :+: BindingT :+: ...). defaultInterfaceT :: (BindingT :<: sym, Let :<: sym, symT ~ Typed sym) => (forall a b. ASTF symT a -> ASTF symT b -> Bool) -> (forall a. ASTF symT a -> Bool) -> CodeMotionInterface symT -- | Perform common sub-expression elimination and variable hoisting codeMotion :: (Equality sym, BindingDomain sym) => CodeMotionInterface sym -> ASTF sym a -> ASTF sym a -- | Construction and elimination of tuples module Language.Syntactic.Functional.Tuple class Select1 tup where type family Sel1 tup select1 :: Select1 tup => tup -> Sel1 tup class Select2 tup where type family Sel2 tup select2 :: Select2 tup => tup -> Sel2 tup class Select3 tup where type family Sel3 tup select3 :: Select3 tup => tup -> Sel3 tup class Select4 tup where type family Sel4 tup select4 :: Select4 tup => tup -> Sel4 tup -- | Construction and elimination of tuples data Tuple sig Tup2 :: Tuple (a :-> (b :-> Full (a, b))) Tup3 :: Tuple (a :-> (b :-> (c :-> Full (a, b, c)))) Tup4 :: Tuple (a :-> (b :-> (c :-> (d :-> Full (a, b, c, d))))) Sel1 :: Tuple (tup :-> Full (Sel1 tup)) Sel2 :: Tuple (tup :-> Full (Sel2 tup)) Sel3 :: Tuple (tup :-> Full (Sel3 tup)) Sel4 :: Tuple (tup :-> Full (Sel4 tup)) instance Language.Syntactic.Interpretation.Equality Language.Syntactic.Functional.Tuple.Tuple instance Language.Syntactic.Interpretation.StringTree Language.Syntactic.Functional.Tuple.Tuple instance Language.Syntactic.Functional.Eval Language.Syntactic.Functional.Tuple.Tuple instance Language.Syntactic.Functional.EvalEnv Language.Syntactic.Functional.Tuple.Tuple env instance Language.Syntactic.Functional.Tuple.Select1 (a, b) instance Language.Syntactic.Functional.Tuple.Select2 (a, b) instance Language.Syntactic.Functional.Tuple.Select1 (a, b, c) instance Language.Syntactic.Functional.Tuple.Select2 (a, b, c) instance Language.Syntactic.Functional.Tuple.Select3 (a, b, c) instance Language.Syntactic.Functional.Tuple.Select1 (a, b, c, d) instance Language.Syntactic.Functional.Tuple.Select2 (a, b, c, d) instance Language.Syntactic.Functional.Tuple.Select3 (a, b, c, d) instance Language.Syntactic.Functional.Tuple.Select4 (a, b, c, d) instance Language.Syntactic.Syntax.Symbol Language.Syntactic.Functional.Tuple.Tuple instance Language.Syntactic.Interpretation.Render Language.Syntactic.Functional.Tuple.Tuple -- | Well-scoped terms module Language.Syntactic.Functional.WellScoped -- | Environment extension class Ext ext orig -- | Remove the extension of an environment unext :: Ext ext orig => ext -> orig -- | Return the amount by which an environment has been extended diff :: (Ext ext orig, Num a) => Proxy ext -> Proxy orig -> a -- | Lookup in an extended environment lookEnv :: Ext env (a, e) => Proxy e -> Reader env a -- | Well-scoped variable binding -- -- Well-scoped terms are introduced to be able to evaluate without type -- casting. The implementation is inspired by "Typing Dynamic Typing" -- (Baars and Swierstra, ICFP 2002, -- http://doi.acm.org/10.1145/581478.581494) where expressions are -- represented as (essentially) Reader env a after -- "compilation". However, a major difference is that "Typing Dynamic -- Typing" starts from an untyped term, and thus needs (safe) dynamic -- type casting during compilation. In contrast, the denotational -- semantics of BindingWS (the Eval instance) uses no type -- casting. data BindingWS sig VarWS :: Proxy e -> BindingWS (Full (Reader env a)) LamWS :: BindingWS (Reader (a, e) b :-> Full (Reader e (a -> b))) -- | Higher-order interface for well-scoped variable binding -- -- Inspired by Conor McBride's "I am not a number, I am a classy hack" -- (http://mazzo.li/epilogue/index.html%3Fp=773.html). lamWS :: (BindingWS :<: sym) => ((forall env. (Ext env (a, e)) => ASTF sym (Reader env a)) -> ASTF sym (Reader (a, e) b)) -> ASTF sym (Reader e (a -> b)) -- | Evaluation of open well-scoped terms evalOpenWS :: Eval s => env -> ASTF s (Reader env a) -> a -- | Evaluation of closed well-scoped terms evalClosedWS :: Eval s => ASTF s (Reader () a) -> a -- | Mapping from a symbol signature -- --
--   a :-> b :-> Full c
--   
-- -- to -- --
--   Reader env a :-> Reader env b :-> Full (Reader env c)
--   
-- | Mapping from a symbol signature -- --
--   Reader e a :-> Reader e b :-> Full (Reader e c)
--   
-- -- to -- --
--   a :-> b :-> Full c
--   
-- | Wrap a symbol to give it a LiftReader signature data ReaderSym sym sig ReaderSym :: Proxy env -> sym sig -> ReaderSym sym (LiftReader env sig) -- | Well-scoped AST type WS sym env a = ASTF (BindingWS :+: ReaderSym sym) (Reader env a) -- | Convert the representation of variables and binders from -- BindingWS to Binding. The latter is easier to analyze, -- has a Render instance, etc. fromWS :: WS sym env a -> ASTF (Binding :+: sym) a -- | Make a smart constructor for well-scoped terms. smartWS has any -- type of the form: -- --
--   smartWS :: (sub :<: sup, bsym ~ (BindingWS :+: ReaderSym sup))
--       => sub (a :-> b :-> ... :-> Full x)
--       -> ASTF bsym (Reader env a) -> ASTF bsym (Reader env b) -> ... -> ASTF bsym (Reader env x)
--   
smartWS :: (Signature sig, Signature sig', sub :<: sup, bsym ~ (BindingWS :+: ReaderSym sup), f ~ SmartFun bsym sig', sig' ~ SmartSig f, bsym ~ SmartSym f, sig' ~ LiftReader env sig, Denotation (LiftReader env sig) ~ DenotationM (Reader env) sig, LowerReader (LiftReader env sig) ~ sig, Reader env a ~ DenResult sig') => sub sig -> f instance Language.Syntactic.Functional.WellScoped.Ext env env instance (Language.Syntactic.Functional.WellScoped.Ext env e, ext ~ (a, env)) => Language.Syntactic.Functional.WellScoped.Ext ext e instance Language.Syntactic.Syntax.Symbol Language.Syntactic.Functional.WellScoped.BindingWS instance Language.Syntactic.Functional.Eval Language.Syntactic.Functional.WellScoped.BindingWS instance Language.Syntactic.Functional.Eval sym => Language.Syntactic.Functional.Eval (Language.Syntactic.Functional.WellScoped.ReaderSym sym) -- | Syntactic instance for functions -- -- This module is based on having Binding in the domain. For -- BindingT import module Language.Syntactic.Sugar.BindingT -- instead. module Language.Syntactic.Sugar.Binding instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Domain a ~ dom, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Domain b ~ dom, Language.Syntactic.Functional.Binding Language.Syntactic.Syntax.:<: dom) => Language.Syntactic.Sugar.Syntactic (a -> b) -- | Syntactic instance for functions -- -- This module is based on having BindingT in the domain. For -- Binding import module Language.Syntactic.Sugar.Binding -- instead. module Language.Syntactic.Sugar.BindingT instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Syntax.Typed dom, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Domain b ~ Language.Syntactic.Syntax.Typed dom, Language.Syntactic.Functional.BindingT Language.Syntactic.Syntax.:<: dom, Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal a), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal b)) => Language.Syntactic.Sugar.Syntactic (a -> b) -- | Syntactic instance for Remon using Binding to -- handle variable binding module Language.Syntactic.Sugar.Monad -- | One-layer sugaring of monadic actions sugarMonad :: (Binding :<: sym, MONAD m :<: sym) => ASTF sym (m a) -> Remon sym m (ASTF sym a) instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Domain a ~ sym, Language.Syntactic.Functional.Binding Language.Syntactic.Syntax.:<: sym, Language.Syntactic.Functional.MONAD m Language.Syntactic.Syntax.:<: sym, Data.Typeable.Internal.Typeable m, Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal a)) => Language.Syntactic.Sugar.Syntactic (Language.Syntactic.Functional.Remon sym m a) -- | Syntactic instance for Remon using BindingT to -- handle variable binding module Language.Syntactic.Sugar.MonadT -- | One-layer sugaring of monadic actions sugarMonad :: (BindingT :<: sym, MONAD m :<: sym, symT ~ Typed sym, Typeable m, Typeable a) => ASTF symT (m a) -> Remon symT m (ASTF symT a) instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Domain a ~ symT, symT ~ Language.Syntactic.Syntax.Typed sym, Language.Syntactic.Functional.BindingT Language.Syntactic.Syntax.:<: sym, Language.Syntactic.Functional.MONAD m Language.Syntactic.Syntax.:<: sym, Data.Typeable.Internal.Typeable m, Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal a)) => Language.Syntactic.Sugar.Syntactic (Language.Syntactic.Functional.Remon symT m a) -- | Syntactic instances for tuples module Language.Syntactic.Sugar.Tuple instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain b, Language.Syntactic.Functional.Tuple.Tuple Language.Syntactic.Syntax.:<: Language.Syntactic.Sugar.Domain a) => Language.Syntactic.Sugar.Syntactic (a, b) instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Syntactic c, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain b, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain c, Language.Syntactic.Functional.Tuple.Tuple Language.Syntactic.Syntax.:<: Language.Syntactic.Sugar.Domain a) => Language.Syntactic.Sugar.Syntactic (a, b, c) instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Syntactic c, Language.Syntactic.Sugar.Syntactic d, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain b, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain c, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain d, Language.Syntactic.Functional.Tuple.Tuple Language.Syntactic.Syntax.:<: Language.Syntactic.Sugar.Domain a) => Language.Syntactic.Sugar.Syntactic (a, b, c, d) -- | Syntactic instances for tuples and Typed symbol domains module Language.Syntactic.Sugar.TupleT instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Syntactic b, Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal a), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal b), Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Syntax.Typed sym, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain b, Language.Syntactic.Functional.Tuple.Tuple Language.Syntactic.Syntax.:<: sym) => Language.Syntactic.Sugar.Syntactic (a, b) instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Syntactic c, Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal a), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal b), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal c), Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Syntax.Typed sym, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain b, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain c, Language.Syntactic.Functional.Tuple.Tuple Language.Syntactic.Syntax.:<: sym) => Language.Syntactic.Sugar.Syntactic (a, b, c) instance (Language.Syntactic.Sugar.Syntactic a, Language.Syntactic.Sugar.Syntactic b, Language.Syntactic.Sugar.Syntactic c, Language.Syntactic.Sugar.Syntactic d, Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal a), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal b), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal c), Data.Typeable.Internal.Typeable (Language.Syntactic.Sugar.Internal d), Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Syntax.Typed sym, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain b, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain c, Language.Syntactic.Sugar.Domain a ~ Language.Syntactic.Sugar.Domain d, Language.Syntactic.Functional.Tuple.Tuple Language.Syntactic.Syntax.:<: sym) => Language.Syntactic.Sugar.Syntactic (a, b, c, d)