of the error.
2.6
Attempts to provide better explanations from
the W algorithm
Several attempts have been made to provide better explanations from the W algo- rithm, such as the work of [LG06], which describes how error suggestions may even be presented by calling the compiler (i.e. running the W algorithm) multiple times on a piece of user code. Their system is split up into three different pieces:
• Changer. The changer takes as input a program which contains a type error
and outputs changes that make the program well typed. It verifies such
changes make the program typable by replacing sections of user code with dummy expressions that typecheck, then calling the compiler again to verify that the code is then typable. This process is broken down further into an enumerator which suggests syntax changes and a searcher, which guides where changes should be attempted.
• Type checker. This remains unchanged from the original compiler implemen- tation but is used to detect which changes that are output from the Changer actually succeed in making the program typable.
• Ranker. The ranker will prioritize the changes that have been checked and verified by the type checker and will display messages accordingly.
The reporting system described here is a wrapper around the compiler that intercepts the type checker’s error messages and then produces better ones. This approach is not entirely dissimilar to the approach taken by Braßel [Bra04], as discussed below. As this is a patch on the Ocaml sources which simply looks at the untypable program as reported by the Ocaml compiler, attempts some changes by taking the point of error and replacing the code surrounding it by dummy expressions, runs the type inference algorithm of the Ocaml compiler again, analyses the results, and repeats as necessary, this approach has the following properties:
• Installation is trivial. The patch is simply added to the compiler and then the build process is completed as normal.
• Any new features which are added to the language will automatically be sup- ported, at least in some sense. Depending on the complexity and properties
2.6. ATTEMPTS TO PROVIDE BETTER EXPLANATIONS FROM THE W ALGORITHM
of the new language feature, it may be the case that errors involving this new feature will perhaps not be of an excellent quality, but it is likely that it would be able to provide the programmer with some assistance.
• If the type system is edited in some minor way, the error reporting of would likely be unaffected.
• Use of the implementation is trivial, a command line argument is simply added to the invocation of the Ocaml compiler.
In the approach given in [LG06], a better error is located in an untypable pro- gram by identifying interesting nodes in the abstract syntax tree, by taking the root of the tree and replacing a node with a wildcard character. If the code typechecks after this is put in place, then this node is marked as interesting and recursion moves to the children of that node in order to find further interesting nodes. Oth- erwise, that node and its children are deemed uninteresting. It is pointed out that this has some nice properties because it will always find interesting nodes (the root is always going to be interesting, because replacing that with the wildcard opera- tor will typecheck, naturally), and no recursion is done into subtrees which don’t contain a type error (if the father of a given node is not interesting, then the given node can’t be interesting either).
Given this approach however, there are the drawbacks that the error locations located by this approach as when run of programs with multiple programming errors, the results may be of a lesser quality. This is the case because these ap- proaches look for any way to make the program typable, rather than looking for all the locations that a program can be made typable.
Other techniques to locate possible fixes are used, such as replacing variables with other variables which are in the same scope, swapping, removing or inserting some arguments of functions involved in an error and removing type annotations, etc. All of these techniques when used will attempt to locate better suggested fixes for the user to look at.
Another related system is that of Braßel [Bra04] named TypeHope, which is a system which runs on programs written in the logic language Curry with the objec- tive of locating and providing possible solutions to type errors in those programs. It is designed to operate in a similar way to human programmers when attempting to locate the source of an error by replacing entire functions by dummy definitions and then checking whether the program is now typable.
When this system is run on an untypable section of code, it locates regions where a fix may be possible and assigns dummy types to expressions inside those
2.6. ATTEMPTS TO PROVIDE BETTER EXPLANATIONS FROM THE W ALGORITHM
locations. It then checks whether the code is made typable after making such a change by repeating a call to the compiler, and if it is, repeats the process on any sub-expressions of the expression that was turned into a dummy expression in order to locate a more accurate source of error. In TypeHope, writing a constraint generator and constraint solver is not necessary, as one can just send modified code to the compiler to test if it is typable after a dummy expression has been added to the program.
In order that the user is not flooded with lots of possible fixes for the program, TypeHope assigns a weight to each possible solution it finds based on a compound of factors (including how many types would need to be changed etc), and attempts to show the most promising correction points first. To find these most promising correction points, TypeHope prefers inner correction points to outer ones in a given expression, and prefers fix points which are located in a function further away in the call graph from the function which is deemed to contain an error.
Figure 2.5 shows the code example presented in the [Bra04], where
reverse (x:xs) = reverse xs ++ x is mistakenly entered in the program instead of of
reverse (x:xs) = reverse xs ++ [x] at line 2.
Figure 2.5 Example code for TypeHope to analyze
1 r e v e r s e [] = [] 2 r e v e r s e ( x : xs ) = r e v e r s e xs ++ x 3 4 l a s t ls = h e a d ( r e v e r s e ls ) 5 6 i n i t = r e v e r s e . t a i l . r e v e r s e 7 8 r o t a t e ls = l a s t ls : i n i t ls
TypeHope begins searching for the error in the location that the compiler re- ported, line 8, by replacing the right hand side with a dummy function. As this removes the previous type error, TypeHope inspects the call graph for the right hand side expression and notices that the farthest away function is reverse (as both the last and init functions call reverse, and reverse calls no other function). The right hand side definition of reverse is then replaced with a dummy function call and it is noticed that the program is now typable, so the definition of this