Safe Haskell | None |
---|---|
Language | Haskell2010 |
Basics for implementing functional EDSLs
Synopsis
- newtype Name = Name Integer
- data Literal sig where
- data Construct sig where
- Construct :: Signature sig => String -> Denotation sig -> Construct sig
- data Binding sig where
- maxLam :: Project Binding s => AST s a -> Name
- lam_template :: Project Binding sym => (Name -> sym (Full a)) -> (Name -> ASTF sym b -> ASTF sym (a -> b)) -> (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)
- lam :: Binding :<: sym => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)
- fromDeBruijn :: Binding :<: sym => ASTF sym a -> ASTF sym a
- data BindingT sig where
- maxLamT :: Project BindingT sym => AST sym a -> Name
- lamT_template :: Project BindingT sym => (Name -> sym (Full a)) -> (Name -> ASTF sym b -> ASTF sym (a -> b)) -> (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)
- lamT :: (BindingT :<: sym, Typeable a) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)
- lamTyped :: (sym ~ Typed s, BindingT :<: s, Typeable a, Typeable b) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)
- class BindingDomain sym where
- data Let sig where
- data MONAD m sig where
- newtype Remon sym m a where
- desugarMonad :: (MONAD m :<: sym, Typeable a, Typeable m) => Remon sym m (ASTF sym a) -> ASTF sym (m a)
- desugarMonadTyped :: (MONAD m :<: s, sym ~ Typed s, Typeable a, Typeable m) => Remon sym m (ASTF sym a) -> ASTF sym (m a)
- freeVars :: BindingDomain sym => AST sym sig -> Set Name
- allVars :: BindingDomain sym => AST sym sig -> Set Name
- renameUnique' :: forall sym a. BindingDomain sym => [Name] -> ASTF sym a -> ASTF sym a
- renameUnique :: BindingDomain sym => ASTF sym a -> ASTF sym a
- type AlphaEnv = [(Name, Name)]
- alphaEq' :: (Equality sym, BindingDomain sym) => AlphaEnv -> ASTF sym a -> ASTF sym b -> Bool
- alphaEq :: (Equality sym, BindingDomain sym) => ASTF sym a -> ASTF sym b -> Bool
- type family Denotation sig
- class Eval s where
- evalSym :: s sig -> Denotation sig
- evalDen :: Eval s => AST s sig -> Denotation sig
- type family DenotationM (m :: * -> *) sig
- liftDenotationM :: forall m sig proxy1 proxy2. Monad m => SigRep sig -> proxy1 m -> proxy2 sig -> Denotation sig -> DenotationM m sig
- type RunEnv = [(Name, Dynamic)]
- class EvalEnv sym env where
- compileSym :: proxy env -> sym sig -> DenotationM (Reader env) sig
- compileSymDefault :: forall proxy env sym sig. Eval sym => SigRep sig -> proxy env -> sym sig -> DenotationM (Reader env) sig
- evalOpen :: EvalEnv sym env => env -> ASTF sym a -> a
- evalClosed :: EvalEnv sym RunEnv => ASTF sym a -> a
Syntactic constructs
Variable name
Instances
Enum Name Source # | |
Eq Name Source # | |
Integral Name Source # | |
Num Name Source # | |
Ord Name Source # | |
Real Name Source # | |
Defined in Language.Syntactic.Functional toRational :: Name -> Rational # | |
Show Name Source # | |
NFData Name Source # | |
Defined in Language.Syntactic.Functional | |
EvalEnv BindingT RunEnv Source # | |
Defined in Language.Syntactic.Functional compileSym :: proxy RunEnv -> BindingT sig -> DenotationM (Reader RunEnv) sig Source # |
data Literal sig where Source #
Literal
Instances
Symbol Literal Source # | |
StringTree Literal Source # | |
Defined in Language.Syntactic.Functional | |
Render Literal Source # | |
Equality Literal Source # | |
Eval Literal Source # | |
Defined in Language.Syntactic.Functional evalSym :: Literal sig -> Denotation sig Source # | |
EvalEnv Literal env Source # | |
Defined in Language.Syntactic.Functional compileSym :: proxy env -> Literal sig -> DenotationM (Reader env) sig Source # |
data Construct sig where Source #
Generic N-ary syntactic construct
Construct
gives a quick way to introduce a syntactic construct by giving its name and semantic
function.
Construct :: Signature sig => String -> Denotation sig -> Construct sig |
Instances
Symbol Construct Source # | |
StringTree Construct Source # | |
Defined in Language.Syntactic.Functional | |
Render Construct Source # | |
Equality Construct Source # | |
Eval Construct Source # | |
Defined in Language.Syntactic.Functional evalSym :: Construct sig -> Denotation sig Source # | |
EvalEnv Construct env Source # | |
Defined in Language.Syntactic.Functional compileSym :: proxy env -> Construct sig -> DenotationM (Reader env) sig Source # |
data Binding sig where Source #
Variables and binders
Instances
NFData1 Binding Source # | |
Defined in Language.Syntactic.Functional | |
Symbol Binding Source # | |
StringTree Binding Source # | |
Defined in Language.Syntactic.Functional | |
Render Binding Source # | |
Equality Binding Source # |
|
BindingDomain Binding Source # | |
:: Project Binding sym | |
=> (Name -> sym (Full a)) | Variable symbol constructor |
-> (Name -> ASTF sym b -> ASTF sym (a -> b)) | Lambda constructor |
-> (ASTF sym a -> ASTF sym b) | |
-> ASTF sym (a -> b) |
Higher-order interface for variable binding for domains based on Binding
Assumptions:
- The body
f
does not inspect its argument. - Applying
f
to a term with ordered binders results in a term with ordered binders \[1\].
\[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, https://emilaxelsson.github.io/documents/axelsson2013using.pdf).
lam :: Binding :<: sym => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b) Source #
Higher-order interface for variable binding
This function is lamT_template
specialized to domains sym
satisfying
(
.Binding
:<:
sym)
data BindingT sig where Source #
Typed variables and binders
VarT :: Typeable a => Name -> BindingT (Full a) | |
LamT :: Typeable a => Name -> BindingT (b :-> Full (a -> b)) |
Instances
NFData1 BindingT Source # | |
Defined in Language.Syntactic.Functional | |
Symbol BindingT Source # | |
StringTree BindingT Source # | |
Defined in Language.Syntactic.Functional | |
Render BindingT Source # | |
Equality BindingT Source # |
|
BindingDomain BindingT Source # | |
EvalEnv BindingT RunEnv Source # | |
Defined in Language.Syntactic.Functional compileSym :: proxy RunEnv -> BindingT sig -> DenotationM (Reader RunEnv) sig Source # |
:: Project BindingT sym | |
=> (Name -> sym (Full a)) | Variable symbol constructor |
-> (Name -> ASTF sym b -> ASTF sym (a -> b)) | Lambda constructor |
-> (ASTF sym a -> ASTF sym b) | |
-> ASTF sym (a -> b) |
Higher-order interface for variable binding
Assumptions:
- The body
f
does not inspect its argument. - Applying
f
to a term with ordered binders results in a term with ordered binders \[1\].
\[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, https://emilaxelsson.github.io/documents/axelsson2013using.pdf).
lamT :: (BindingT :<: sym, Typeable a) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b) Source #
Higher-order interface for variable binding
This function is lamT_template
specialized to domains sym
satisfying
(
.BindingT
:<:
sym)
lamTyped :: (sym ~ Typed s, BindingT :<: s, Typeable a, Typeable b) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b) Source #
Higher-order interface for variable binding
This function is lamT_template
specialized to domains sym
satisfying
(sym ~
.Typed
s, BindingT
:<:
s)
class BindingDomain sym where Source #
Domains that "might" include variables and binders
prVar :: sym sig -> Maybe Name Source #
prLam :: sym sig -> Maybe Name Source #
renameBind :: (Name -> Name) -> sym sig -> sym sig Source #
Rename a variable or a lambda (no effect for other symbols)
Instances
BindingDomain sym Source # | |
BindingDomain BindingT Source # | |
BindingDomain Binding Source # | |
BindingDomain sym => BindingDomain (Typed sym) Source # | |
BindingDomain sym => BindingDomain (AST sym) Source # | |
(BindingDomain sym1, BindingDomain sym2) => BindingDomain (sym1 :+: sym2) Source # | |
BindingDomain sym => BindingDomain (sym :&: i) Source # | |
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.
The provided string is just a tag and has nothing to do with the name of the variable of the second argument (if that argument happens to be a lambda). However, a back end may use the tag to give a sensible name to the generated variable.
The string tag may be empty.
Instances
Symbol Let Source # | |
StringTree Let Source # | |
Defined in Language.Syntactic.Functional | |
Render Let Source # | |
Equality Let Source # | |
Eval Let Source # | |
Defined in Language.Syntactic.Functional evalSym :: Let sig -> Denotation sig Source # | |
EvalEnv Let env Source # | |
Defined in Language.Syntactic.Functional compileSym :: proxy env -> Let sig -> DenotationM (Reader env) sig Source # |
data MONAD m sig where Source #
Monadic constructs
See "Generic Monadic Constructs for Embedded Languages" (Persson et al., IFL 2011 https://emilaxelsson.github.io/documents/persson2011generic.pdf).
Instances
Symbol (MONAD m) Source # | |
StringTree (MONAD m) Source # | |
Defined in Language.Syntactic.Functional | |
Render (MONAD m) Source # | |
Equality (MONAD m) Source # | |
Monad m => Eval (MONAD m) Source # | |
Defined in Language.Syntactic.Functional evalSym :: MONAD m sig -> Denotation sig Source # | |
Monad m => EvalEnv (MONAD m) env Source # | |
Defined in Language.Syntactic.Functional compileSym :: proxy env -> MONAD m sig -> DenotationM (Reader env) sig Source # |
newtype Remon sym m a where Source #
Reifiable monad
See "Generic Monadic Constructs for Embedded Languages" (Persson et al., IFL 2011 https://emilaxelsson.github.io/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.
Instances
Monad (Remon dom m) Source # | |
Functor (Remon sym m) Source # | |
Applicative (Remon sym m) Source # | |
Defined in Language.Syntactic.Functional | |
(sym ~ Typed s, Syntactic a, Domain a ~ sym, BindingT :<: s, MONAD m :<: s, Typeable m, Typeable (Internal a)) => Syntactic (Remon sym m a) Source # | |
Defined in Language.Syntactic.Sugar.MonadTyped | |
(Syntactic a, Domain a ~ sym, Binding :<: sym, MONAD m :<: sym, Typeable m, Typeable (Internal a)) => Syntactic (Remon sym m a) Source # | |
Defined in Language.Syntactic.Sugar.Monad | |
type Domain (Remon sym m a) Source # | |
Defined in Language.Syntactic.Sugar.MonadTyped | |
type Domain (Remon sym m a) Source # | |
Defined in Language.Syntactic.Sugar.Monad | |
type Internal (Remon sym m a) Source # | |
Defined in Language.Syntactic.Sugar.MonadTyped | |
type Internal (Remon sym m a) Source # | |
Defined in Language.Syntactic.Sugar.Monad |
desugarMonad :: (MONAD m :<: sym, Typeable a, Typeable m) => Remon sym m (ASTF sym a) -> ASTF sym (m a) Source #
One-layer desugaring of monadic actions
desugarMonadTyped :: (MONAD m :<: s, sym ~ Typed s, Typeable a, Typeable m) => Remon sym m (ASTF sym a) -> ASTF sym (m a) Source #
One-layer desugaring of monadic actions
Free and bound variables
freeVars :: BindingDomain sym => AST sym sig -> Set Name Source #
Get the set of free variables in an expression
allVars :: BindingDomain sym => AST sym sig -> Set Name Source #
Get the set of variables (free, bound and introduced by lambdas) in an expression
renameUnique' :: forall sym a. BindingDomain sym => [Name] -> ASTF sym a -> ASTF sym a Source #
Rename the bound variables in a term
The free variables are left untouched. The bound variables are given unique names using as small names as possible. The first argument is a list of reserved names. Reserved names and names of free variables are not used when renaming bound variables.
renameUnique :: BindingDomain sym => ASTF sym a -> ASTF sym a Source #
Rename the bound variables in a term
The free variables are left untouched. The bound variables are given unique names using as small names as possible. Names of free variables are not used when renaming bound variables.
Alpha-equivalence
alphaEq' :: (Equality sym, BindingDomain sym) => AlphaEnv -> ASTF sym a -> ASTF sym b -> Bool Source #
alphaEq :: (Equality sym, BindingDomain sym) => ASTF sym a -> ASTF sym b -> Bool Source #
Alpha-equivalence
Evaluation
type family Denotation sig Source #
Semantic function type of the given symbol signature
Instances
type Denotation (Full a) Source # | |
Defined in Language.Syntactic.Functional | |
type Denotation (a :-> sig) Source # | |
Defined in Language.Syntactic.Functional |
evalSym :: s sig -> Denotation sig Source #
Instances
type family DenotationM (m :: * -> *) sig Source #
Monadic denotation; mapping from a symbol signature
a :-> b :-> Full c
to
m a -> m b -> m c
Instances
type DenotationM m (Full a) Source # | |
Defined in Language.Syntactic.Functional | |
type DenotationM m (a :-> sig) Source # | |
Defined in Language.Syntactic.Functional |
liftDenotationM :: forall m sig proxy1 proxy2. Monad m => SigRep sig -> proxy1 m -> proxy2 sig -> Denotation sig -> DenotationM m sig Source #
Lift a Denotation
to DenotationM
class EvalEnv sym env where Source #
Evaluation
Nothing
compileSym :: proxy env -> sym sig -> DenotationM (Reader env) sig Source #
default compileSym :: (Symbol sym, Eval sym) => proxy env -> sym sig -> DenotationM (Reader env) sig Source #
Instances
compileSymDefault :: forall proxy env sym sig. Eval sym => SigRep sig -> proxy env -> sym sig -> DenotationM (Reader env) sig Source #
Simple implementation of compileSym
from a Denotation