Ignore:
Timestamp:
May 13, 2025, 1:17:50 PM (4 months ago)
Author:
Mike Brooks <mlbrooks@…>
Branches:
master
Children:
0528d79
Parents:
7d02d35 (diff), 2410424 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/fangren_yu_MMath/intro.tex

    r7d02d35 rbd72f517  
    3030
    3131\section{Overloading}
    32 
     32\label{s:Overloading}
     33
     34\vspace*{-5pt}
    3335\begin{quote}
    3436There are only two hard things in Computer Science: cache invalidation and \emph{naming things}. --- Phil Karlton
    3537\end{quote}
     38\vspace*{-5pt}
    3639Overloading allows programmers to use the most meaningful names without fear of name clashes within a program or from external sources, like include files.
    37 Experience from \CC and \CFA developers shows the type system can implicitly and correctly disambiguates the majority of overloaded names, \ie it is rare to get an incorrect selection or ambiguity, even among hundreds of overloaded (variables and) functions.
     40Experience from \CC and \CFA developers shows the type system can implicitly and correctly disambiguate the majority of overloaded names, \ie it is rare to get an incorrect selection or ambiguity, even among hundreds of overloaded (variables and) functions.
    3841In many cases, a programmer is unaware of name clashes, as they are silently resolved, simplifying the development process.
    3942
    4043Disambiguating among overloads is implemented by examining each call site and selecting the best matching overloaded function based on criteria like the types and number of arguments and the return context.
    41 Since the hardware does not support mixed-mode operands, @2 + 3.5@, the type system must disallow it or (safely) convert the operands to a common type.
     44Since the hardware does not support mixed-mode operands, such as @2 + 3.5@, the type system must disallow it or (safely) convert the operands to a common type.
    4245Like overloading, the majority of mixed-mode conversions are silently resolved, simplifying the development process.
    4346This approach matches with programmer intuition and expectation, regardless of any \emph{safety} issues resulting from converted values.
     
    4952As well, many namespace systems provide a mechanism to open their scope returning to normal overloading, \ie no qualification.
    5053While namespace mechanisms are very important and provide a number of crucial program-development features, protection from overloading is overstated.
    51 Similarly, lexical nesting is another place where overloading occurs.
     54Similarly, lexical nesting is another place where duplicate naming issues arise.
    5255For example, in object-oriented programming, class member names \newterm{shadow} names within members.
    53 Some programmers, qualify all member names with @class::@ or @this->@ to make them unique from names defined in members.
    54 Even nested lexical blocks result in shadowing, \eg multiple nested loop-indices called @i@.
    55 Again, coding styles exist requiring all variables in nested block to be unique to prevent name shadowing.
     56Some programmers qualify all member names with @class::@ or @this->@ to make them unique from names defined in members.
     57Even nested lexical blocks result in shadowing, \eg multiple nested loop-indices called @i@, silently changing the meaning of @i@ at lower scope levels.
     58Again, coding styles exist requiring all variables in nested block to be unique to prevent name shadowing problems.
    5659Depending on the language, these possible ambiguities can be reported (as warnings or errors) and resolved explicitly using some form of qualification and/or cast.
    57 
    58 Formally, overloading is defined by Strachey as \newterm{ad hoc polymorphism}:
     60For example, if variables can be overloaded, shadowed variables of different type can produce ambiguities, indicating potential problems in lower scopes.
     61
     62Formally, overloading is defined by Strachey as one kind of \newterm{ad hoc polymorphism}:
     63\vspace*{-5pt}
    5964\begin{quote}
    6065In ad hoc polymorphism there is no single systematic way of determining the type of the result from the type of the arguments.
     
    6368It seems, moreover, that the automatic insertion of transfer functions by the compiling system is limited to this.~\cite[p.~37]{Strachey00}
    6469\end{quote}
     70\vspace*{-5pt}
    6571where a \newterm{transfer function} is an implicit conversion to help find a matching overload:
     72\vspace*{-5pt}
    6673\begin{quote}
    6774The problem of dealing with polymorphic operators is complicated by the fact that the range of types sometimes overlap.
     
    6976The functions which perform this operation are known as transfer functions and may either be used explicitly by the programmer, or, in some systems, inserted automatically by the compiling system.~\cite[p.~35]{Strachey00}
    7077\end{quote}
     78\vspace*{-5pt}
    7179The differentiating characteristic between parametric polymorphism and overloading is often stated as: polymorphic functions use one algorithm to operate on arguments of many different types, whereas overloaded functions use a different algorithm for each type of argument.
    7280A similar differentiation is applicable for overloading and default parameters.
     
    128136\end{cfa}
    129137the overloaded names @S@ and @E@ are separated into the type and object domain, and C uses the type kinds @struct@ and @enum@ to disambiguate the names.
    130 In general, types are not overloaded because inferencing them is difficult to imagine in a statically programming language.
     138In general, types are not overloaded because inferencing them is difficult to imagine in a statically typed programming language.
    131139\begin{cquote}
    132140\setlength{\tabcolsep}{26pt}
     
    181189\noindent
    182190\newterm{General overloading} occurs when the type-system \emph{knows} a function's parameters and return types (or a variable's type for variable overloading).
    183 In functional programming-languages, there is always a return type (except for a monad).
     191In functional programming-languages, there is always a return type.
    184192If a return type is specified, the compiler does not have to inference the function body.
    185193For example, the compiler has complete knowledge about builtin types and their overloaded arithmetic operators.
     
    214222Hence, parametric overloading requires additional information about the universal types to make them useful.
    215223
    216 This additional information often comes as a set of operations a type must supply (@trait@/-@concept@) and these operations can then be used in the body of the function.
    217 \begin{cfa}
    218 forall( T | T ?@++@( T, T ) ) T inc( T t ) { return t@++@; }
     224This additional information often comes as a set of operations that must be supply for a type, \eg \CFA/Rust/Go have traits, \CC template has concepts, Haskell has type-classes.
     225These operations can then be used in the body of the function to manipulate the type's value.
     226Here, a type binding to @T@ must have available a @++@ operation with the specified signature.
     227\begin{cfa}
     228forall( T | @T ?++( T, T )@ ) // trait
     229T inc( T t ) { return t@++@; } // change type value
    219230int i = 3
    220231i = inc( i )
     
    222233\end{cfa}
    223234Given a qualifying trait, are its elements inferred or declared?
    224 In the above example, the type system infers @int@ for @T@, infers it needs a @++@ operator that takes an @int@ and returns an @int@, and finds this function in the enclosing environment (\eg standard prelude).
     235In the example, the type system infers @int@ for @T@, infers it needs an appropriately typed @++@ operator, and finds it in the enclosing environment, possibly in the language's prelude defining basic types and their operations.
    225236This implicit inferencing is expensive if matched with implicit conversions when there is no exact match.
    226237Alternatively, types opt-in to traits via declarations.
     
    420431\subsection{Operator Overloading}
    421432
    422 Virtually all programming languages provide general overloading of the arithmetic operators across the basic computational types using the number and type of parameters and returns.
     433Many programming languages provide general overloading of the arithmetic operators~\cite{OperOverloading} across the basic computational types using the number and type of parameters and returns.
    423434However, in some languages, arithmetic operators may not be first class, and hence, cannot be overloaded.
    424435Like \CC, \CFA allows general operator overloading for user-defined types.
     
    438449\subsection{Function Overloading}
    439450
    440 Both \CFA and \CC allow general overloading for functions, as long as their prototypes differ in the number and type of parameters and returns.
     451Many programming languages provide general overloading for functions~\cite{FuncOverloading}, as long as their prototypes differ in the number and type of parameters.
     452A few programming languages also use the return type for selecting overloaded functions \see{below}.
    441453\begin{cfa}
    442454void f( void );                 $\C[2in]{// (1): no parameter}$
     
    445457f( 'A' );                               $\C{// select (2)}\CRT$
    446458\end{cfa}
    447 The type system examines each call size and first looks for an exact match and then a best match using conversions.
     459The type system examines each call site and first looks for an exact match and then a best match using conversions.
    448460
    449461Ada, Scala, and \CFA type-systems also use the return type in resolving a call, to pinpoint the best overloaded name.
    450 Essentailly, the return types are \emph{reversed curried} into output parameters of the function.
     462Essentially, the return types are \emph{reversed curried} into output parameters of the function.
    451463For example, in many programming languages with overloading, the following functions are ambiguous without using the return type.
    452464\begin{cfa}
     
    478490\begin{cfa}
    479491void foo( double d );
    480 int v;                              $\C[2in]{// (1)}$
     492int v;                                  $\C[2in]{// (1)}$
    481493double v;                               $\C{// (2) variable overloading}$
    482494foo( v );                               $\C{// select (2)}$
     
    487499}
    488500\end{cfa}
    489 It is interesting that shadow overloading is considered a normal programming-language feature with only slight software-engineering problems.
     501It is interesting that shadowing \see{namespace pollution in \VRef{s:Overloading}} is considered a normal programming-language feature with only slight software-engineering problems.
    490502However, variable overloading within a scope is often considered dangerous, without any evidence to corroborate this claim.
    491503In contrast, function overloading in \CC occurs silently within the global scope from @#include@ files all the time without problems.
     
    554566The following covers these issues, and why this scheme is not amenable with the \CFA type system.
    555567
    556 One of the first and powerful type-inferencing system is Hindley--Milner~\cite{Damas82}.
     568One of the first and most powerful type-inferencing systems is Hindley--Milner~\cite{Damas82}.
    557569Here, the type resolver starts with the types of the program constants used for initialization and these constant types flow throughout the program, setting all variable and expression types.
    558570\begin{cfa}
     
    579591Note, return-type inferencing goes in the opposite direction to Hindley--Milner: knowing the type of the result and flowing back through an expression to help select the best possible overloads, and possibly converting the constants for a best match.
    580592
    581 In simpler type-inferencing systems, such as C/\CC/\CFA, there are more specific usages.
     593There are multiple ways to indirectly specify a variable's type, \eg from a prior variable or expression.
    582594\begin{cquote}
    583595\setlength{\tabcolsep}{10pt}
     
    606618\end{tabular}
    607619\end{cquote}
    608 The two important capabilities are:
     620Here, @type(expr)@ computes the same type as @auto@ righ-hand expression.
     621The advantages are:
    609622\begin{itemize}[topsep=0pt]
    610623\item
     
    616629This issue is exaggerated with \CC templates, where type names are 100s of characters long, resulting in unreadable error messages.
    617630\item
    618 Ensuring the type of secondary variables, match a primary variable.
     631Ensuring the type of secondary variables match a primary variable.
    619632\begin{cfa}
    620633int x; $\C{// primary variable}$
     
    625638\end{itemize}
    626639Note, the use of @typeof@ is more restrictive, and possibly safer, than general type-inferencing.
     640\begin{cquote}
     641\setlength{\tabcolsep}{20pt}
     642\begin{tabular}{@{}ll@{}}
    627643\begin{cfa}
    628644int x;
     
    630646type(x) z = ... // complex expression
    631647\end{cfa}
    632 Here, the types of @y@ and @z@ are fixed (branded), whereas with type inferencing, the types of @y@ and @z@ are potentially unknown.
     648&
     649\begin{cfa}
     650int x;
     651auto y = ... // complex expression
     652auto z = ... // complex expression
     653\end{cfa}
     654\end{tabular}
     655\end{cquote}
     656On the left, the types of @y@ and @z@ are fixed (branded), whereas on the right, the types of @y@ and @z@ can fluctuate.
    633657
    634658
    635659\subsection{Type-Inferencing Issues}
    636660
    637 Each kind of type-inferencing system has its own set of issues that flow onto the programmer in the form of convenience, restrictions, or confusions.
     661Each kind of type-inferencing system has its own set of issues that affect the programmer in the form of convenience, restrictions, or confusions.
    638662
    639663A convenience is having the compiler use its overarching program knowledge to select the best type for each variable based on some notion of \emph{best}, which simplifies the programming experience.
     
    643667For example, if a change is made in an initialization expression, it can cascade type changes producing many other changes and/or errors.
    644668At some point, a variable's type needs to remain constant and the initializing expression needs to be modified or be in error when it changes.
    645 Often type-inferencing systems allow restricting (\newterm{branding}) a variable or function type, so the complier can report a mismatch with the constant initialization.
     669Often type-inferencing systems allow restricting (\newterm{branding}) a variable or function type, so the compiler can report a mismatch with the constant initialization.
    646670\begin{cfa}
    647671void f( @int@ x, @int@ y ) {  // brand function prototype
     
    657681As a result, understanding and changing the code becomes almost impossible.
    658682Types provide important clues as to the behaviour of the code, and correspondingly to correctly change or add new code.
    659 In these cases, a programmer is forced to re-engineer types, which is fragile, or rely on a fancy IDE that can re-engineer types for them.
     683In these cases, a programmer is forced to re-engineer types, which is fragile, or rely on an IDE that can re-engineer types for them.
    660684For example, given:
    661685\begin{cfa}
     
    670694In this situation, having the type name or its short alias is essential.
    671695
    672 \CFA's type system tries to prevent type-resolution mistakes by relying heavily on the type of the left-hand side of assignment to pinpoint the right types within an expression.
     696\CFA's type system tries to prevent type-resolution mistakes by relying heavily on the type of the left-hand side of assignment to pinpoint correct types within an expression.
    673697Type inferencing defeats this goal because there is no left-hand type.
    674 Fundamentally, type inferencing tries to magic away variable types from the programmer.
    675 However, this results in lazy programming with the potential for poor performance and safety concerns.
    676 Types are as important as control-flow in writing a good program, and should not be masked, even if it requires the programmer to think!
    677 A similar issue is garbage collection, where storage management is magicked away, often resulting in poor program design and performance.\footnote{
    678 There are full-time Java consultants, who are hired to find memory-management problems in large Java programs.}
    679 The entire area of Computer-Science data-structures is obsessed with time and space, and that obsession should continue into regular programming.
    680 Understanding space and time issues is an essential part of the programming craft.
    681 Given @typedef@ and @typeof@ in \CFA, and the strong desire to use the left-hand type in resolution, the decision was made not to support implicit type-inferencing in the type system.
     698Fundamentally, type inferencing tries to remove explicit typing from programming.
     699However, writing down types is an important aspect of good programming, as it provides a check of the programmer's expected type and the actual type.
     700Thinking carefully about types is similar to thinking carefully about date structures, often resulting in better performance and safety.
     701Similarly, thinking carefully about storage management in unmanaged languages is an important aspect of good programming, versus implicit storage management (garbage collection) in managed language.\footnote{
     702There are full-time Java consultants, who are hired to find memory-management problems in large Java programs, \eg Monika Beckworth.}
     703Given @typedef@ and @typeof@, and the strong desire to use the left-hand type in resolution, no attempt has been made in \CFA to support implicit type-inferencing.
    682704Should a significant need arise, this decision can be revisited.
    683705
     
    702724int i, * ip = identity( &i );
    703725\end{cfa}
    704 Unlike \CC template functions, \CFA polymorphic functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
     726Unlike \CC template functions, \CFA polymorphic functions are compatible with \emph{separate compilation}, preventing compilation and code bloat.
    705727
    706728To constrain polymorphic types, \CFA uses \newterm{type assertions}~\cite[pp.~37-44]{Alphard} to provide further type information, where type assertions may be variable or function declarations that depend on a polymorphic type variable.
     
    710732int val = twice( twice( 3 ) );  $\C{// val == 12}$
    711733\end{cfa}
    712 Parametric polymorphism and assertions occur in existing type-unsafe (@void *@) C functions, like @qsort@ for sorting an array of unknown values.
     734The closest approximation to parametric polymorphism and assertions in C is type-unsafe (@void *@) functions, like @qsort@ for sorting an array of unknown values.
    713735\begin{cfa}
    714736void qsort( void * base, size_t nmemb, size_t size, int (*cmp)( const void *, const void * ) );
     
    761783The @sized@ assertion passes size and alignment as a data object has no implicit assertions.
    762784Both assertions are used in @malloc@ via @sizeof@ and @_Alignof@.
    763 In practise, this polymorphic @malloc@ is unwrapped by the C compiler and the @if@ statement is elided producing a type-safe call to @malloc@ or @memalign@.
     785In practice, this polymorphic @malloc@ is unwrapped by the C compiler and the @if@ statement is elided producing a type-safe call to @malloc@ or @memalign@.
    764786
    765787This mechanism is used to construct type-safe wrapper-libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions.
     
    787809forall( T @| sumable( T )@ )   // use trait
    788810T sum( T a[$\,$], size_t size ) {
    789         @T@ total = 0;          // initialize by 0 constructor
     811        @T@ total = 0;            // initialize by 0 constructor
    790812        for ( i; size )
    791                 total @+=@ a[i];    // select appropriate +
     813                total @+=@ a[i];        // select appropriate +
    792814        return total;
    793815}
     
    795817\end{tabular}
    796818\end{cquote}
    797 Traits are implemented by flatten them at use points, as if written in full by the programmer.
     819Traits are implemented by flattening them at use points, as if written in full by the programmer.
    798820Flattening often results in overlapping assertions, \eg operator @+@.
    799821Hence, trait names play no part in type equivalence.
     
    821843Write bespoke data structures for each context.
    822844While this approach is flexible and supports integration with the C type checker and tooling, it is tedious and error prone, especially for more complex data structures.
     845
    823846\item
    824847Use @void *@-based polymorphism, \eg the C standard library functions @bsearch@ and @qsort@, which allow for the reuse of code with common functionality.
    825848However, this approach eliminates the type checker's ability to ensure argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that is otherwise unnecessary.
     849
    826850\item
    827 Use preprocessor macros, similar to \CC @templates@, to generate code that is both generic and type checked, but errors may be difficult to interpret.
    828 Furthermore, writing and using complex preprocessor macros is difficult and inflexible.
     851Use an internal macro capability, like \CC @templates@, to generate code that is both generic and type checked, but errors may be difficult to interpret.
     852Furthermore, writing complex template macros is difficult and complex.
     853
     854\item
     855Use an external macro capability, like M4~\cite{M4}, to generate code that is generic code, but errors may be difficult to interpret.
     856Like internal macros, writing and using external macros is equally difficult and complex.
    829857\end{enumerate}
    830858
     
    857885\end{tabular}
    858886\end{cquote}
     887\label{s:GenericImplementation}
    859888\CFA generic types are \newterm{fixed} or \newterm{dynamic} sized.
    860889Fixed-size types have a fixed memory layout regardless of type parameters, whereas dynamic types vary in memory layout depending on the type parameters.
     
    883912For software-engineering reasons, the set assertions would be refactored into a trait to allow alternative implementations, like a Java \lstinline[language=java]{interface}.
    884913
    885 In summation, the \CFA type system inherits \newterm{nominal typing} for concrete types from C, and adds \newterm{structural typing} for polymorphic types.
    886 Traits are used like interfaces in Java or abstract base-classes in \CC, but without the nominal inheritance relationships.
    887 Instead, each polymorphic function or generic type defines the structural type needed for its execution, which is fulfilled at each call site from the lexical environment, like Go~\cite{Go} or Rust~\cite{Rust} interfaces.
    888 Hence, new lexical scopes and nested functions are used extensively to create local subtypes, as in the @qsort@ example, without having to manage a nominal inheritance hierarchy.
     914In summation, the \CFA type system inherits \newterm{nominal typing} for concrete types from C;
     915however, without inheritance in \CFA, nominal typing cannot be extended to polymorphic subtyping.
     916Instead, \CFA adds \newterm{structural typing} and uses it to generate polymorphism.
     917Here, traits are like interfaces in Java or abstract base-classes in \CC, but without the nominal inheritance relationships.
     918Instead, each polymorphic function or generic type defines the structural requirements needed for its execution, which is fulfilled at each call site from the lexical environment, like Go~\cite{Go} or Rust~\cite{Rust} interfaces.
     919Hence, lexical scopes and nested functions are used extensively to mimic subtypes, as in the @qsort@ example, without managing a nominal inheritance hierarchy.
    889920
    890921
     
    902933general\footnote{overloadable entities: V $\Rightarrow$ variable, O $\Rightarrow$ operator, F $\Rightarrow$ function, M $\Rightarrow$ member}
    903934                                                & O\footnote{except assignment}/F       & O/F/M & V/O/F & M\footnote{not universal}     & O/M   & O/F/M & no    & no    \\
    904 general constraints\footnote{T $\Rightarrow$ parameter type, \# $\Rightarrow$ parameter number, N $\Rightarrow$ parameter name; R $\Rightarrow$ return type}
     935general constraints\footnote{T $\Rightarrow$ parameter type, \# $\Rightarrow$ parameter count, N $\Rightarrow$ parameter name; R $\Rightarrow$ return type}
    905936                                                & T/\#//R\footnote{parameter names can be used to disambiguate among overloads but not create overloads}
    906937                                                                        & T/\#  & T/\#/R        & T/\#  & T/\#/N/R      & T/\#/N/R      & T/\#/N        & T/R \\
     
    9991030
    10001031However, the parameter operations are severely restricted because universal types have few operations.
    1001 For example, swift provides a @print@ operation for its universal type, and the java @Object@ class provides general methods: @toString@, @hashCode@, @equals@, @finalize@, \etc.
     1032For example, Swift provides a @print@ operation for its universal type, and the Java @Object@ class provides general methods: @toString@, @hashCode@, @equals@, @finalize@, \etc.
    10021033This restricted mechanism still supports a few useful functions, where the parameters are abstract entities, \eg:
    10031034\begin{swift}
     
    10091040\end{swift}
    10101041To make a universal function useable, an abstract description is needed for the operations used on the parameters within the function body.
    1011 Type matching these operations can occur by discover using techniques like \CC template expansion, or explicit stating, \eg interfaces, subtyping (inheritance), assertions (traits), type classes, type bounds.
     1042Type matching these operations can be done by using techniques like \CC template expansion, or explicit stating, \eg interfaces, subtyping (inheritance), assertions (traits), type classes, type bounds.
    10121043The mechanism chosen can affect separate compilation or require runtime type information (RTTI).
    10131044\begin{description}
     
    10301061
    10311062\begin{figure}
    1032 \setlength{\tabcolsep}{15pt}
     1063\setlength{\tabcolsep}{12pt}
    10331064\begin{tabular}{@{}ll@{}}
    10341065\multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{Haskell}} \\
     
    10361067forall( T ) trait sumable {
    10371068        void ?{}( T &, zero_t );
    1038         T ?+=?( T &, T );
    1039 };
     1069        T ?+=?( T &, T );  };
    10401070forall( T | sumable( T ) )
    10411071T sum( T a[], size_t size ) {
    10421072        T total = 0;
    10431073        for ( i; size ) total += a[i];
    1044         return total;
    1045 }
     1074        return total;  }
    10461075struct S { int i, j; };
    10471076void ?{}( S & s, zero_t ) { s.[i, j] = 0; }
     
    10491078void ?{}( S & s, int i, int j ) { s.[i, j] = [i, j]; }
    10501079S ?+=?( S & l, S r ) { l.[i, j] += r.[i, j]; }
    1051 
    1052 int main() {
    1053         int ia[] = { 1, 2, 3 };
    1054         sout | sum( ia, 3 );        // trait inference
    1055         double da[] = { 1.5, 2.5, 3.5 };
    1056         sout | sum( da, 3 );        // trait inference
    1057         S sa[] = { {1, 1}, {2, 2}, {3, 3 } };
    1058         sout | sum( sa, 3 ).[i, j]; // trait inference
    1059 }
     1080int main() {            // trait inferencing
     1081        sout | sum( (int []){ 1, 2, 3 }, 3 );
     1082        sout | sum( (double []){ 1.5, 2.5, 3.5 }, 3 );
     1083        sout | sum( (S []){ {1,1}, {2,2}, {3,3} }, 3 ).[i, j];  }
     1084
     1085
     1086
    10601087\end{cfa}
    10611088&
     
    10641091        szero :: a
    10651092        sadd :: a -> a -> a
    1066 
    10671093ssum ::  Sumable a $=>$ [a] -> a
    10681094ssum (x:xs) = sadd x (ssum xs)
    10691095ssum [] = szero
    1070 
    1071 
    1072 
    10731096data S = S Int Int deriving Show
    10741097@instance Sumable Int@ where
     
    10771100@instance Sumable Float@ where
    10781101        szero = 0.0
    1079    sadd = (+)
     1102        sadd = (+)
    10801103@instance Sumable S@ where
    10811104        szero = S 0 0
     
    10871110\end{haskell}
    10881111\end{tabular}
    1089 \caption{Implicitly/Explicitly Trait Inferencing}
    1090 \label{f:ImplicitlyExplicitlyTraitInferencing}
     1112\caption{Implicit/Explicit Trait Inferencing}
     1113\label{f:ImplicitExplicitTraitInferencing}
    10911114\end{figure}
    10921115
    10931116One differentiating feature among these specialization techniques is the ability to implicitly or explicitly infer the trait information at a class site.
    1094 \VRef[Figure]{f:ImplicitlyExplicitlyTraitInferencing} compares the @sumable@ trait and polymorphic @sum@ function \see{\VRef{s:Traits}} for \CFA and Haskell.
     1117\VRef[Figure]{f:ImplicitExplicitTraitInferencing} compares the @sumable@ trait and polymorphic @sum@ function \see{\VRef{s:Traits}} for \CFA and Haskell.
    10951118Here, the \CFA type system inferences the trait functions at each call site, so no additional specification is necessary by the programmer.
    10961119The Haskell program requires the programmer to explicitly bind the trait and to each type that can be summed.
     
    11021125\end{ada}
    11031126Finally, there is a belief that certain type systems cannot support general overloading, \eg Haskell.
    1104 As \VRef[Table]{t:OverloadingFeatures} shows, there are multiple languages with both general and parametric overloading, so the decision to not support general overloading is based on the opinion of the language designers and the type system they choose, not any reason in type theory.
     1127As \VRef[Table]{t:OverloadingFeatures} shows, there are multiple languages with both general and parametric overloading, so the decision to not support general overloading is based on design choices made by the language designers not any reason in type theory.
    11051128
    11061129The fourth row classifies if conversions are attempted beyond exact match.
     
    11211144The details of compiler optimization work are covered in a previous technical report~\cite{Yu20}, which essentially forms part of this thesis.
    11221145\item
    1123 The thesis presents a systematic review of the new features added to the \CFA language and its type system.
     1146This thesis presents a systematic review of the new features added to the \CFA language and its type system.
    11241147Some of the more recent inclusions to \CFA, such as tuples and generic structure types, were not well tested during development due to the limitation of compiler performance.
    11251148Several issues coming from the interactions of various language features are identified and discussed in this thesis;
Note: See TracChangeset for help on using the changeset viewer.