-- 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]. -- -- For more information, see "A Generic Abstract Syntax Model for -- Embedded Languages" (ICFP 2012): -- --
-- 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 a 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 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 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 -- | 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 -- | 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 [overlap ok] Typeable1 Full instance [overlap ok] Typeable2 :-> instance [overlap ok] Eq a => Eq (Full a) instance [overlap ok] Show a => Show (Full a) instance [overlap ok] Functor Full instance [overlap ok] Functor ((:->) a) instance [overlap ok] (Functor sym1, Functor sym2) => Functor (sym1 :+: sym2) instance [overlap ok] (Foldable sym1, Foldable sym2) => Foldable (sym1 :+: sym2) instance [overlap ok] (Traversable sym1, Traversable sym2) => Traversable (sym1 :+: sym2) instance [overlap ok] sym1 :<: sym3 => sym1 :<: (sym2 :+: sym3) instance [overlap ok] sym1 :<: (sym1 :+: sym2) instance [overlap ok] sym :<: sym instance [overlap ok] sub :<: sup => sub :<: AST sup instance [overlap ok] Project sub sup instance [overlap ok] Project sym1 sym3 => Project sym1 (sym2 :+: sym3) instance [overlap ok] Project sym1 (sym1 :+: sym2) instance [overlap ok] Project sym sym instance [overlap ok] Project sub sup => Project sub (AST sup) instance [overlap ok] Signature sig => Signature (a :-> sig) instance [overlap ok] Signature (Full a) instance [overlap ok] Functor sym => Functor (AST sym) -- | Generic traversals of AST terms module Data.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 Data.Syntactic.Interpretation -- | Higher-kinded equality class Equality e equal :: Equality e => e a -> e b -> Bool 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) ++ ")" renderSym :: Render sym => sym sig -> String 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 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 StringTree Empty instance (StringTree sym1, StringTree sym2) => StringTree (sym1 :+: sym2) instance Render sym => Show (ASTF sym a) instance Render Empty instance (Render sym1, Render sym2) => Render (sym1 :+: sym2) instance Equality Empty instance (Equality sym1, Equality sym2) => Eq ((:+:) sym1 sym2 a) instance (Equality sym1, Equality sym2) => Equality (sym1 :+: sym2) instance Equality sym => Eq (AST sym a) instance Equality sym => Equality (AST 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 Data.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 instance [overlap ok] (Syntactic a, Domain a ~ sym, ia ~ Internal a, SyntacticN f fi) => SyntacticN (a -> f) (AST sym (Full ia) -> fi) instance [overlap ok] (Syntactic f, Domain f ~ sym, fi ~ AST sym (Full (Internal f))) => SyntacticN f fi instance [overlap ok] Syntactic (ASTF sym a) -- | Construct for decorating symbols or expressions with additional -- information module Data.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 () instance StringTree expr => StringTree (expr :&: info) instance Render expr => Render (expr :&: info) instance Equality expr => Equality (expr :&: info) instance Project sub sup => Project sub (sup :&: info) -- | The basic parts of the syntactic library module Data.Syntactic -- | Basics for implementing functional EDSLs module Data.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 a Construct :: String -> Denotation sig -> Construct sig -- | Variables and binders data Binding a 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: -- --
-- a :-> b :-> Full c ---- -- to -- --
-- m a -> m b -> m c ---- | Lift a Denotation to DenotationM liftDenotationM :: (Monad m, Signature sig) => proxy1 m -> proxy2 sig -> Denotation sig -> DenotationM m sig -- | Runtime environment type RunEnv = [(Name, Dynamic)] -- | Evaluation class EvalEnv sym env compileSym :: EvalEnv sym env => proxy env -> sym sig -> DenotationM (Reader env) sig -- | Simple implementation of compileSym from a Denotation compileSymDefault :: (Eval sym, Signature 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 -- | Environment extension class Ext ext orig unext :: Ext ext orig => ext -> orig 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 a 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 a 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 [overlap ok] Eq Name instance [overlap ok] Ord Name instance [overlap ok] Num Name instance [overlap ok] Enum Name instance [overlap ok] Real Name instance [overlap ok] Integral Name instance [overlap ok] Functor (Remon sym m) instance [overlap ok] Eval sym => Eval (ReaderSym sym) instance [overlap ok] Eval BindingWS instance [overlap ok] (Ext env e, ext ~ (a, env)) => Ext ext e instance [overlap ok] Ext env env instance [overlap ok] EvalEnv BindingT RunEnv instance [overlap ok] Monad m => EvalEnv (MONAD m) env instance [overlap ok] EvalEnv Construct env instance [overlap ok] EvalEnv sym env => EvalEnv (sym :&: info) env instance [overlap ok] EvalEnv Empty env instance [overlap ok] (EvalEnv sym1 env, EvalEnv sym2 env) => EvalEnv (sym1 :+: sym2) env instance [overlap ok] Monad m => Eval (MONAD m) instance [overlap ok] Eval Construct instance [overlap ok] Eval sym => Eval (sym :&: info) instance [overlap ok] Eval Empty instance [overlap ok] (Eval s, Eval t) => Eval (s :+: t) instance [overlap ok] Monad m => Monad (Remon dom m) instance [overlap ok] Applicative m => Applicative (Remon sym m) instance [overlap ok] StringTree (MONAD m) instance [overlap ok] Equality (MONAD m) instance [overlap ok] Render (MONAD m) instance [overlap ok] BindingDomain sym instance [overlap ok] BindingDomain BindingT instance [overlap ok] BindingDomain Binding instance [overlap ok] BindingDomain sym => BindingDomain (AST sym) instance [overlap ok] BindingDomain sym => BindingDomain (sym :&: i) instance [overlap ok] (BindingDomain sym1, BindingDomain sym2) => BindingDomain (sym1 :+: sym2) instance [overlap ok] StringTree BindingT instance [overlap ok] Render BindingT instance [overlap ok] Equality BindingT instance [overlap ok] StringTree Binding instance [overlap ok] Render Binding instance [overlap ok] Equality Binding instance [overlap ok] Show Name instance [overlap ok] StringTree Construct instance [overlap ok] Equality Construct instance [overlap ok] Render Construct -- | Syntactic instance for functions -- -- This module is based on having Binding in the domain. For -- BindingT import module Data.Syntactic.Sugar.BindingT -- instead module Data.Syntactic.Sugar.Binding instance (Syntactic a, Domain a ~ dom, Syntactic b, Domain b ~ dom, Binding :<: dom) => Syntactic (a -> b) -- | Syntactic instance for functions -- -- This module is based on having BindingT in the domain. For -- Binding import module Data.Syntactic.Sugar.Binding -- instead module Data.Syntactic.Sugar.BindingT instance (Syntactic a, Domain a ~ dom, Syntactic b, Domain b ~ dom, BindingT :<: dom, Typeable (Internal a)) => Syntactic (a -> b) -- | Syntactic instance for Remon using Binding to -- handle variable binding module Data.Syntactic.Sugar.Monad -- | One-layer sugaring of monadic actions sugarMonad :: Binding :<: sym => ASTF sym (m a) -> Remon sym m (ASTF sym a) instance (Syntactic a, Domain a ~ sym, Binding :<: sym, MONAD m :<: sym, Monad m) => Syntactic (Remon sym m a) -- | Syntactic instance for Remon using BindingT to -- handle variable binding module Data.Syntactic.Sugar.MonadT -- | One-layer sugaring of monadic actions sugarMonad :: (BindingT :<: sym, Typeable a) => ASTF sym (m a) -> Remon sym m (ASTF sym a) instance (Syntactic a, Domain a ~ sym, BindingT :<: sym, MONAD m :<: sym, Monad m, Typeable (Internal a)) => Syntactic (Remon sym m a)