Top quality type error Messages

Publication date

2005-09-20

Authors

Heeren, B.J.

Editors

Advisors

Supervisors

DOI

Document Type

Dissertation
Open Access logo

License

Abstract

Flaws in computer software are a fact of life, both in small and large-scale applications. Compilers for modern programming languages accommodate many program analyses for finding mistakes at compile-time (statically). These analyses detect a significant portion of errors automatically: this makes program analyses a valuable and indispensable tool for developing reliable, high quality software. Type checking is perhaps the most popular and best studied form of static analysis. This analysis guarantees that functions (or methods) are never applied to incompatible arguments, and is traditionally an important part of functional programming languages (e.g., ML and Haskell). One common feature of ML and Haskell is that they are implicitly typed: no type annotations in the program are required. Instead, these languages rely on an effective type inference algorithm, which automatically deduces all types. This inference algorithm has the pleasing property that it finds principal (or most general) types. In fact, the inference algorithm not only recovers type information, it also detects type inconsistencies in programs, which are generally caused by mistakes made by the programmer. In most compilers, however, the algorithm for type inference is not designed to provide good feedback, but rather focuses on performance. As a result, the type error messages that are reported by these algorithms can be difficult to understand, especially for beginning programmers. This thesis is entirely devoted to improve the type error messages for a functional programming language. Ideally, we should follow a human-like inference strategy, and depart from the mechanical order in which standard inference algorithms proceed. This entails, for example, a global analysis of a program, which depends on heuristics that capture expert knowledge. We may even anticipate common errors and provide additional information for special classes of mistakes. We have reached the above results by pursuing a constraint-based approach to type inference. The typing problem is first mapped to a set of type constraints, which is then passed to a specialized constraint solver. Because there is no best type inference algorithm that suits everyone, we present a parameterized framework, which can be instantiated and customized according to one's personal preferences. We propose a set of type inference directives to personalize the type inference process even further. Type inference directives change the error message facility, but without losing soundness of the underlying type system. For instance, these directives make it possible to phrase error messages in terms of a specific domain, which makes them very suitable for creating a close integration of the DSL and the host language. In addition, directives allow to tune the error messages to the level of expertise of a specific group of programmers. All type inference techniques that we propose have been implemented in the Helium compiler, which covers almost the entire Haskell 98 standard. This compiler has been used for the introductory functional programming courses at Utrecht University, by students without any prior knowledge of functional programming. The implementation affirms that our approach scales to a full-blown programming language.

Keywords

constraints, type inference, type error messages, type systems, directives, domain-specific programming, functional programming, heuristics, compiler construction

Citation