Improving Type Error Diagnosis Peter J. Stuckey Department of Computer Science and Software Engineering, University of Melbourne, 3010, Australia pjs@cs.mu.oz.au Martin Sulzmann School of Computing, National University of Singapore S16 Level 5, 3 Science Drive 2, Singapore 117543 sulzmann@comp.nus.edu.sg Jeremy Wazny Department of Computer Science and Software Engineering, University of Melbourne, 3010, Australia jeremyrw@cs.mu.oz.au Abstract We present a number of methods for providing improved type er- ror reports in the Haskell and Chameleon programming languages. We build upon our previous work [19] where we first introduced the idea of discovering type errors by translating the typing prob- lem into a constraint problem and looking for minimal unsatisfiable subsets of constraints. This allowed us to find precise sets of pro- gram locations which are in conflict with each other. Here we ex- tend this approach by extracting additional useful information from these minimal unsatisfiable sets. This allows us to report errors as conflicts amongst a number of possible, candidate types. The advantage of our approach is that it offers implementors the flex- ibility to employ heuristics to select where, amongst all the loca- tions involved, an error should be reported. In addition, we present methods for providing improved subsumption and ambiguity error reporting. Categories and Subject Descriptors D.3.2 [Programming Languages]: Language Classifications— Applicative (functional) languages; D.3.3 [Programming Languages]: Language Constructs and Features—Polymor- phism,Constraints; F.3.3 [Logics and Meanings of Programs]: Studies of Program Constructs—Type structure General Terms Languages, Theory Keywords type inference, type debugging, Hindley/Milner, overloading, type classes, constraints 1 Introduction In previous work [19], we introduced a comprehensive type de- bugging framework which has been implemented as part of the Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Haskell’04, September 22, 2004, Snowbird, Utah, USA. Copyright 2004 ACM 1-58113-850-4/04/0009 ...$5.00 Chameleon system [20]. The basic idea is to map expressions to constraints. Upon encountering a type error, i.e. unsatisfiable con- straint, we extract the minimal amount of information necessary for explaining those errors; we look for minimal unsatisfiable con- straints. Values attached to individual constraints refer back to pro- gram locations that contributed to those constraints. Highlighting those locations allows us to identify expressions which contributed to the type error. Our approach naturally deals with type classes; we are able to highlight type class rules (such as instances and func- tional dependencies) which are part of the type error. The difficulty with type error diagnosis, in general, is that there might be several minimal unsatisfiable constraints (which corre- spond to several type error explanations), yet it may only be com- putationally feasible to find one minimal unsatisfiable constraint. If there is a common subset of all errors, we can efficiently compute the intersection of all minimal unsatisfiable constraints. Under our original error reporting scheme, we first highlight all locations corresponding to a minimal unsatisfiable constraint and then, separately also highlight locations which are part of the inter- section of all minimal unsatisfiable constraint (if non-empty). Ob- viously, we would like to provide for a more meaningful full type error explanation e.g. in terms of a textual message. Throughout the paper, we compare the results of our error reporting approach to the output of GHC [5] version 6. We feel that GHC has the best type error reporting of all the current Haskell implemen- tations. Note that we often reformat error messages, maintaining their basic structure, to fit in a single column. EXAMPLE 1. Consider the following ill-typed program where the highlighted fragments of program text refer to one possible minimal unsatisfiable subset of constraints. insert x [] = x insert x( y:ys) | x > y = y : insert x ys | otherwise = x : y: ys ✷ The mistake here is that in the first clause, x is returned (supposedly as the result of inserting x into an empty list.) In the second (correct) clause the result is a list whose elements have the same type as x. The problem then is that the return type of insert cannot both be t x and [t x ]. However, this might not be immediately obvious by looking at the highlighted program text, in particular since no types are actually reported. Attempting to compile this program using the Haskell compiler GHC, we get the following error message. insert.hs:2: Occurs check: cannot construct the infinite type: a = [a] Expected type: [a]