myriad of typos
[phd-thesis.git] / dsl / class.tex
index 9db7e20..c64bd44 100644 (file)
@@ -2,13 +2,12 @@
 
 \input{subfilepreamble}
 
-\setcounter{chapter}{0}
+\setcounter{chapter}{1}
 
 \begin{document}
 \input{subfileprefix}
 \chapter{Deep embedding with class}%
 \label{chp:classy_deep_embedding}
-
 \begin{chapterabstract}
        The two flavours of \gls{DSL} embedding are shallow and deep embedding.
        In functional languages, shallow embedding models the language constructs as functions in which the semantics are embedded.
@@ -35,7 +34,7 @@ Consequently, adding new semantics, i.e.\ novel functions, is straightforward.
 It can be stated that the language constructs are embedded in the functions that form a semantics.
 If one wants to add a language construct, all semantics functions must be revisited and revised to avoid ending up with partial functions.
 
-This juxtaposition has been known for many years \citep{reynolds_user-defined_1978} and discussed by many others \citep{krishnamurthi_synthesizing_1998} but most famously dubbed the \emph{expression problem} by Wadler \citep{wadler_expression_1998}:
+This juxtaposition has been known for many years \citep{reynolds_user-defined_1978} and discussed by many others \citep{krishnamurthi_synthesizing_1998} but most famously dubbed the \emph{expression problem} by \citet{wadler_expression_1998}:
 
 \begin{quote}
        The \emph{expression problem} is a new name for an old problem.
@@ -179,7 +178,7 @@ instance Sub_t Printer_t where
        sub_t (P_t e1) (P_t e2) = P_t ("(" ++ e1 ++ "-" ++ e2 ++ ")")
 \end{lstHaskellLhstex}
 
-\section{Lifting the backends}%
+\section{Lifting the interpretations}%
 Let us rethink the deeply embedded \gls{DSL} design.
 Remember that in shallow embedding, the semantics are embedded in the language construct functions.
 Obtaining extensibility both in constructs and semantics was accomplished by abstracting the semantics functions to type classes, making the constructs overloaded in the semantics.
@@ -382,7 +381,7 @@ However, the implementation of semantics such as transformation or optimisation
 In shallow embedding, the implementation for these types of semantics is difficult because there is no tangible abstract syntax tree.
 In off-the-shelf deep embedding this is effortless since the function can pattern match on the constructor or structures of constructors.
 
-To demonstrate intensional analyses in classy deep embedding we write an optimizer that removes addition and subtraction by zero.
+To demonstrate intensional analyses in classy deep embedding we write an optimiser that removes addition and subtraction by zero.
 In classy deep embedding, adding new semantics means first adding a new type class housing the function including the machinery for the extension constructor.
 
 \begin{lstHaskellLhstex}
@@ -401,7 +400,7 @@ instance Opt_3 v => GDict (OptDict_3 v) where
        gdict = OptDict_3 opt_3
 \end{lstHaskellLhstex}
 
-The implementation of the optimizer for the \haskelllhstexinline{Expr_3} data type is no complicated task.
+The implementation of the optimiser for the \haskelllhstexinline{Expr_3} data type is no complicated task.
 The only interesting bit occurs in the \haskelllhstexinline{Add_3} constructor, where we pattern match on the optimised children to determine whether an addition with zero is performed.
 If this is the case, the addition is removed.
 
@@ -540,7 +539,7 @@ e1 = neg_4 (Lit_4 42 `Add_4` Lit_4 38) `sub_4` Lit_4 0
 \end{lstHaskellLhstex}
 
 When using classy deep embedding to the fullest, the ability of the compiler to infer very general types expires.
-As a consequence, defining reusable expressions that are overloaded in their semantics requires quite some type class constraints that cannot be inferred by the compiler (yet) if they use many extensions.
+As a consequence, defining reuseable expressions that are overloaded in their semantics requires quite some type class constraints that cannot be inferred by the compiler (yet) if they use many extensions.
 Solving this remains future work.
 For example, the expression $\sim(42-38)+1$ has to be defined as:
 
@@ -549,7 +548,7 @@ e3 :: (Typeable d, GDict (d (Neg_4 d)), GDict (d (Sub_4 d))) => Expr_4 d
 e3 = neg_4 (Lit_4 42 `sub_4` Lit_4 38) `Add_4` Lit_4 1
 \end{lstHaskellLhstex}
 
-\section{\texorpdfstring{\Glsxtrlongpl{GADT}}{Generalised algebraic data types}}%
+\section{Generalised algebraic data types}%
 \Glspl{GADT} are enriched data types that allow the type instantiation of the constructor to be explicitly defined \citep{cheney_first-class_2003,hinze_fun_2003}.
 Leveraging \glspl{GADT}, deeply embedded \glspl{DSL} can be made statically type safe even when different value types are supported.
 Even when \glspl{GADT} are not supported natively in the language, they can be simulated using embedding-projection pairs or equivalence types \citep[\citesection{2.2}]{cheney_lightweight_2002}.
@@ -576,7 +575,7 @@ data Not_g  d a where
        NotLoop_g :: Expr_g d a    -> Not_g d a
 \end{lstHaskellLhstex}
 
-The smart constructors for the language extensions inherit the class constraints of their data types and include a \haskelllhstexinline{Typeable} constraint on the \haskelllhstexinline{d} type variable for it to be usable in the \haskelllhstexinline{Ext_g} constructor as can be seen in the smart constructor for \haskelllhstexinline{Neg_g}:
+The smart constructors for the language extensions inherit the class constraints of their data types and include a \haskelllhstexinline{Typeable} constraint on the \haskelllhstexinline{d} type variable for it to be useable in the \haskelllhstexinline{Ext_g} constructor as can be seen in the smart constructor for \haskelllhstexinline{Neg_g}:
 
 \begin{lstHaskellLhstex}
 neg_g  :: (Typeable d, GDict (d (Neg_g d)), Typeable a, Num a) =>
@@ -603,7 +602,7 @@ class Opt_g   v where
 Now that the shape of the type classes has changed, the dictionary data types and the type classes need to be adapted as well.
 The introduced type variable \haskelllhstexinline{a} is not an argument to the type class, so it should not be an argument to the dictionary data type.
 To represent this type class function, a rank-2 polymorphic function is needed \citep[\citesection{6.4.15}]{ghc_team_ghc_2021}\citep{odersky_putting_1996}.
-Concretely, for the evaluatior this results in the following definitions:
+Concretely, for the evaluator this results in the following definitions:
 
 \begin{lstHaskellLhstex}
 newtype EvalDict_g v = EvalDict_g (forall a. v a -> a)
@@ -633,22 +632,6 @@ instance (Typeable d, GDict (d (Not_g d)), HasOpt_g d) => Opt_g (Not_g d) where
        opt_g (NotLoop_g e) = NotLoop_g (opt_g e)
 \end{lstHaskellLhstex}
 
-\section{Conclusion}%
-
-Classy deep embedding is a novel organically grown embedding technique that alleviates deep embedding from the extensibility problem in most cases.
-
-By abstracting the semantics functions to type classes they become overloaded in the language constructs.
-Thus, making it possible to add new language constructs in a separate type.
-These extensions are brought together in a special extension constructor residing in the main data type.
-This extension case is overloaded by the language construct using a data type containing the class dictionary.
-As a result, orthogonal extension is possible for language constructs and semantics using only little syntactic overhead or type annotations.
-The basic technique only requires---well established through history and relatively standard---existential data types.
-However, if needed, the technique generalises to \glspl{GADT} as well, adding rank-2 types to the list of type system requirements as well.
-Finally, the abstract syntax tree remains observable which makes it suitable for intensional analyses, albeit using occasional dynamic typing for truly cross-extensional transformations.
-
-Defining reusable expressions overloaded in semantics or using multiple semantics on a single expression requires some boilerplate still, getting around this remains future work.
-\Cref{sec:classy_reprise} shows how the boilerplate can be minimised using advanced type system extensions.
-
 \section{Related work}%
 \label{sec:cde:related}
 
@@ -683,27 +666,26 @@ Furthermore, in classy deep embedding, defining (mutual) dependent interpretatio
 
 Hybrid approaches between deep and shallow embedding exist as well.
 For example, \citet{svenningsson_combining_2013} show that by expressing the deeply embedded language in a shallowly embedded core language, extensions can be made orthogonally as well.
-This paper differs from those approaches in the sense that it does not require a core language in which all extensions need to be expressible.
+Classy deep embedding differs from the hybrid approaches in the sense that it does not require the language extensions to be expressible in the core language.
 
 \subsection{Comparison}
-\todo[inline]{text moet beter}
-No \gls{DSL} embedding technique is the silver bullet.
+No \gls{DSL} embedding technique is the silver bullet, there is no way of perfectly satisfying all requirements programmers have.
 \Citet{sun_compositional_2022} provided a thorough comparison of embedding techniques including more axes than just the two stated in the expression problem.
 
 \Cref{tbl:dsl_comparison_brief} shows a variant of their comparison table.
-The first two rows describe the two axes of the original expression problem and the third row describes theadded axis of modular dependency handling as stated by \citeauthor{sun_compositional_2022}.
+The first two rows describe the two axes of the original expression problem and the third row describes the added axis of modular dependency handling as stated by \citeauthor{sun_compositional_2022}.
 The \emph{poly.} style of embedding---including tagless-final---falls short of this requirement.
 
 Intensional analysis is an umbrella term for pattern matching and transformations.
-In shallow embedding, intensional analysis is more complex and requires stateful views describing context but it is possible to implement though.
+In shallow embedding, intensional analysis is more complex and requires stateful views describing context, but it is possible to implement though.
 
-Simple type system describes the whether it is possible to encode this embedding technique with many type system extensions.
+Simple type system describes the whether it is possible to encode this embedding technique without many type system extensions.
 In classy deep embedding, there is either a bit more scaffolding and boilerplate required or advanced type system extensions need to be used.
 
 Little boilerplate denotes the amount of scaffolding and boilerplate required.
 For example, hybrid embedding requires a transcoding step between the deep syntax and the shallow core language.
 
-\begin{table}[ht]
+\begin{table}
        \begin{threeparttable}[b]
                \small
                \caption{Comparison of embedding techniques, extended from \citet[\citesection{3.6}]{sun_compositional_2022}.}%
@@ -725,7 +707,7 @@ For example, hybrid embedding requires a transcoding step between the deep synta
                                                                 & \CIRCLE{}\\
                        Intensional analysis & \LEFTcircle{}\tnote{2} & \CIRCLE{}              & \CIRCLE{}
                                                                 & \LEFTcircle{}\tnote{2} & \LEFTcircle{}\tnote{2} & \CIRCLE{}
-                                                                & \LEFTcircle{}\tnote{3}\\
+                                                                & \CIRCLE{}\tnote{3}\\
                        Simple type system   & \CIRCLE{}              & \CIRCLE{}              & \Circle{}
                                                                 & \CIRCLE{}              & \CIRCLE{}              & \Circle{}
                                                                 & \LEFTcircle{}\tnote{4}\\
@@ -743,6 +725,21 @@ For example, hybrid embedding requires a transcoding step between the deep synta
        \end{threeparttable}
 \end{table}
 
+\section{Conclusion}%
+Classy deep embedding is a novel organically grown embedding technique that alleviates deep embedding from the extensibility problem in most cases.
+
+By abstracting the semantics functions to type classes they become overloaded in the language constructs.
+Thus, making it possible to add new language constructs in a separate type.
+These extensions are brought together in a special extension constructor residing in the main data type.
+This extension case is overloaded by the language construct using a data type containing the class dictionary.
+As a result, orthogonal extension is possible for language constructs and semantics using only little syntactic overhead or type annotations.
+The basic technique only requires---well established through history and relatively standard---existential data types.
+However, if needed, the technique generalises to \glspl{GADT} as well, adding rank-2 types to the list of type system requirements as well.
+Finally, the abstract syntax tree remains observable which makes it suitable for intensional analyses, albeit using occasional dynamic typing for truly cross-extensional transformations.
+
+Defining reuseable expressions overloaded in semantics or using multiple semantics on a single expression requires some boilerplate still, getting around these issues remains future work.
+\Cref{sec:classy_reprise} shows how the boilerplate can be minimised using advanced type system extensions.
+
 \section*{Acknowledgements}
 This research is partly funded by the Royal Netherlands Navy.
 Furthermore, I would like to thank Pieter and Rinus for the fruitful discussions, Ralf for inspiring me to write a functional pearl, and the anonymous reviewers for their valuable and honest comments.
@@ -752,19 +749,19 @@ Furthermore, I would like to thank Pieter and Rinus for the fruitful discussions
 \label{sec:classy_reprise}
 One of the unique selling points of this novel \gls{DSL} embedding technique is that it, in its basic form, does not require advanced type system extensions nor a lot of boilerplate.
 However, generalising the technique to \glspl{GADT} arguably unleashes a cesspool of \emph{unsafe} compiler extensions.
-If we are willing to work with extensions, almost all of the boilerplate can be inferred or generated.
+If we are willing to work with extensions, almost all the boilerplate can be inferred or generated.
 
 In classy deep embedding, the \gls{DSL} datatype is parametrised by a type variable providing a witness to the interpretation on the language.
 When using multiple interpretations, these need to be bundled in a data type.
 Using the \gls{GHC}'s \GHCmod{ConstraintKind} extension, we can make these witnesses explicit, tying into \gls{HASKELL}'s type system immediately.
-Furthermore, this constraint does not necessarily has to be a single constraint, after enabling \GHCmod{DataKinds} and \GHCmod{TypeOperators}, we can encode lists of witnesses instead.
+Furthermore, this constraint does not necessarily have to be a single constraint, after enabling \GHCmod{DataKinds} and \GHCmod{TypeOperators}, we can encode lists of witnesses instead \citep{yorgey_giving_2012}.
 The data type for this list of witnesses is \haskelllhstexinline{Record} as shown in \cref{lst_cbde:record_type}.
 This \gls{GADT} is parametrised by two type variables.
 The first type variable (\haskelllhstexinline{dt}) is the type or type constructor on which the constraints can be applied and the second type variable (\haskelllhstexinline{clist}) is the list of constraints constructors itself.
 This means that when \haskelllhstexinline{Cons} is pattern matched, the overloading of the type class constraint for \haskelllhstexinline{c dt} can be solved by the compiler.
 \GHCmod{KindSignatures} is used to force the kinds of the type parameters and the kind of \haskelllhstexinline{dt} is polymorphic (\GHCmod{PolyKinds}) so that the \haskelllhstexinline{Record} data type can be used for \glspl{DSL} using type classes but also type constructor classes (e.g.\ when using \glspl{GADT}).
 
-\begin{lstHaskellLhstex}[label={lst_cbde:record_type},caption={Data type for a list of constraints}]
+\begin{lstHaskellLhstex}[label={lst_cbde:record_type},caption={Data type for a list of constraints.}]
 data Record (dt :: k) (clist :: [k -> Constraint]) where
        Nil  :: Record dt '[]
        Cons :: c dt => Record dt cs -> Record dt (c ': cs)
@@ -772,7 +769,7 @@ data Record (dt :: k) (clist :: [k -> Constraint]) where
 
 To incorporate this type in the \haskelllhstexinline{Expr} type, the \haskelllhstexinline{Ext} constructor changes from containing a single witness dictionary to a \haskelllhstexinline{Record} type containing all the required dictionaries.
 
-\begin{lstHaskellLhstex}[caption={Data type for a list of constraints}]
+\begin{lstHaskellLhstex}[caption={Main data type with extension constructor.}]
 data Expr c
        = Lit Int
        | Add (Expr c) (Expr c)
@@ -780,9 +777,9 @@ data Expr c
 \end{lstHaskellLhstex}
 
 Furthermore, we define a type class (\haskelllhstexinline{In}) that allows us to extract explicit dictionaries \haskelllhstexinline{Dict} from these records if the constraint can is present in the list.
-Since the constraints become available as soon as the \haskelllhstexinline{Cons} constructor is matched, the implementation is a trivial type-level list traversal.
+Since the constraints become available as soon as the \haskelllhstexinline{Cons} constructor is matched, the implementation is a type-level list traversal.
 
-\begin{lstHaskellLhstex}[caption={Membership functions for constraints}]
+\begin{lstHaskellLhstex}[caption={Membership functions for constraints.}]
 class c `In` cs where
        project :: Record dt cs -> Dict (c dt)
 instance {-# OVERLAPPING #-} c `In` (c ': cs) where
@@ -795,7 +792,7 @@ The final scaffolding is a multi-parameter type class \haskelllhstexinline{Creat
 This type class creates a record structure cons by cons if and only if all type class constraints are available in the list of constraints.
 It is not required to provide instances for this for specific records or type classes, the two instances describe all the required constraints.
 
-\begin{lstHaskellLhstex}[caption={Membership functions for constraints}]
+\begin{lstHaskellLhstex}[caption={Functions for creating the witness records.}]
 class CreateRecord dt c where
        createRecord :: Record dt c
 instance CreateRecord d '[] where
@@ -840,7 +837,7 @@ e0 = neg (neg (Lit 42 `Add` (Lit 38 `subt` Lit 4)))
 \end{lstHaskellLhstex}
 
 It is also possible to define terms in the \gls{DSL} as being overloaded in the interpretation.
-This does require enumerating all the \haskelllhstexinline{CreateRecord} type classes for every extension in a similar fashion as was required for \haskelllhstexinline{GDict}.
+This does require enumerating all the \haskelllhstexinline{CreateRecord} type classes for every extension similarly as was required for \haskelllhstexinline{GDict}.
 At the call site, the concrete list of constraints must be known.
 
 \begin{lstHaskellLhstex}
@@ -849,8 +846,9 @@ e1 :: (Typeable c, CreateRecord (Neg c) c, CreateRecord (Subst c) c)
 e1 = neg (neg (Lit 42 `Add` (Lit 38 `subt` Lit 4)))
 \end{lstHaskellLhstex}
 
-Finally, using the \GHCmod{TypeFamilies} extension, type families can be created for bundling \haskelllhstexinline{`In`} constraints (\haskelllhstexinline{UsingExt}) and \haskelllhstexinline{CreateRecord} constraints (\haskelllhstexinline{DependsOn}), making the syntax even more descriptive.
-E.g.\ \haskelllhstexinline{UsingExt '[A, B, C] c} expands to \haskelllhstexinline{(CreateRecord (A c) c, CreateRecord (B c) c, CreateRecord (C c) c)} and \haskelllhstexinline{DependsOn '[A, B, C] s} expands to \haskelllhstexinline{(A `In` s, B `In` s, C `In` s)}.
+Finally, using the \GHCmod{TypeFamilies} extension, type families can be created for bundling \haskelllhstexinline{`In`} constraints (\haskelllhstexinline{UsingExt}) and \haskelllhstexinline{CreateRecord} constraints \mbox{(\haskelllhstexinline{DependsOn})}, making the syntax even more descriptive.
+E.g.\ \mbox{\haskelllhstexinline{UsingExt '[A, B, C] c}} expands to\newline\haskelllhstexinline{(CreateRecord (A c) c, CreateRecord (B c) c, CreateRecord (C c) c)}.
+\hspace{-1.42284pt} Similarly, \haskelllhstexinline{DependsOn '[A, B, C] s} expands to \haskelllhstexinline{(A `In` s, B `In` s, C `In` s)}.
 
 \begin{lstHaskellLhstex}
 type family UsingExt cs c :: Constraint where
@@ -878,10 +876,13 @@ instance ( UsingExt  '[e_1, e_2, ...] s, DependsOn '[i_1, i_2, ...] s)
 
 With these enhancements, there is hardly any boilerplate required to use classy deep embedding.
 The \haskelllhstexinline{Record} data type; the \haskelllhstexinline{CreateRecord} type class; and the \haskelllhstexinline{UsingExt} and \haskelllhstexinline{DependsOn} type families can be provided as a library only requiring the programmer to create the extension constructors with their respective implementations and smart constructors for language construct extensions.
-The source code for this extension can be found here: \url{https://gitlab.com/mlubbers/classydeepembedding}.
+The source code for this extension can be found here: \url{https://gitlab.com/mlubbers/classydeepembedding}.\footnote{Lubbers, M. (2022): Library and examples for enhanced classy deep embedding.\ Zenodo.\ \href{https://doi.org/10.5281/zenodo.7277498}{10.5281/zenodo.7277498}.}
+It contains examples for expressions, expressions using \glspl{GADT}, detection of sharing in expressions (modelled after \citet{kiselyov_implementing_2011}), a \gls{GADT} version of sharing detection, and a region \gls{DSL} (modelled after \citet{sun_compositional_2022}).
 
 \section{Data types and definitions}%
 \label{sec:cde:appendix}
+This appendix collects all definitions omitted for brevity.
+
 \lstset{basicstyle=\tt\footnotesize}
 \begin{lstHaskellLhstex}[caption={Data type definitions.}]
 data Sub_g d a where
@@ -893,7 +894,7 @@ data Eq_g d a  where
        EqLoop_g  ::                       Expr_g d a -> Eq_g d a
 \end{lstHaskellLhstex}
 
-\begin{lstHaskellLhstex}[caption={Smart constructions.}]
+\begin{lstHaskellLhstex}[caption={Smart constructors.}]
 sub_g :: (Typeable d, GDict (d (Sub_g d)), Eq a, Num a) =>
        Expr_g d a -> Expr_g d a -> Expr_g d a
 sub_g e1 e2 = Ext_g gdict (Sub_g e1 e2)
@@ -921,14 +922,14 @@ instance HasOpt_g OptDict_g where
        getOpt_g (OptDict_g e) = e
 \end{lstHaskellLhstex}
 
-\begin{lstHaskellLhstex}[caption={\texorpdfstring{\haskelllhstexinline{GDict}}{GDict} instances}]
+\begin{lstHaskellLhstex}[caption={{\tt GDict} instances.}]
 instance Print_g v => GDict (PrintDict_g v) where
        gdict = PrintDict_g print_g
 instance Opt_g v   => GDict (OptDict_g v)   where
        gdict = OptDict_g opt_g
 \end{lstHaskellLhstex}
 
-\begin{lstHaskellLhstex}[caption={Evaluator instances}]
+\begin{lstHaskellLhstex}[caption={Evaluator instances.}]
 instance HasEval_g d => Eval_g (Expr_g d) where
        eval_g (Lit_g v)     = v
        eval_g (Add_g e1 e2) = eval_g e1 + eval_g e2
@@ -951,7 +952,7 @@ instance HasEval_g d => Eval_g (Not_g d) where
        eval_g (NotLoop_g e) = eval_g e
 \end{lstHaskellLhstex}
 
-\begin{lstHaskellLhstex}[caption={Printer instances}]
+\begin{lstHaskellLhstex}[caption={Printer instances.}]
 instance HasPrint_g d => Print_g (Expr_g d) where
        print_g (Lit_g v)     = show v
        print_g (Add_g e1 e2) = "(" ++ print_g e1 ++ "+" ++ print_g e2 ++ ")"
@@ -974,7 +975,7 @@ instance HasPrint_g d => Print_g (Not_g d) where
        print_g (NotLoop_g e) = print_g e
 \end{lstHaskellLhstex}
 
-\begin{lstHaskellLhstex}[caption={Optimisation instances}]
+\begin{lstHaskellLhstex}[caption={Optimisation instances.}]
 instance HasOpt_g d => Opt_g (Expr_g d) where
        opt_g (Lit_g v)     = Lit_g v
        opt_g (Add_g e1 e2) = case (opt_g e1, opt_g e2) of