{'fraction_non_alphanumeric': 0.01580135440180587, 'fraction_numerical': 0.0, 'mean_word_length': 4.81311475409836, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
A declarative debugger for Haskell

This thesis is about the design and implementation of a debugging tool which helps Haskell programmers understand why their programs do not work as intended. The traditional debugging technique of examining the program execution step-by-step, popular with imperative languages, is less suitable for Haskell because its unorthodox evaluation strategy is difficult to relate to the structure of the original program source code. We build a debugger which focuses on the high-level logical meaning of a program rather than its evaluation order. This style of debugging is called declarative debugging, and it originated in logic programming languages. At the heart of the debugger is a tree which records information about the evaluation of the program in a manner which is easy to relate to the structure of the program. Links between nodes in the tree reflect logical relationships between entities in the source code. An error diagnosis algorithm is applied to the tree in a top-down fashion, searching for causes of bugs. The search is guided by an oracle, who knows how each part of the program should behave. The oracle is normally a human — typically the person who wrote the program — however, much of its behaviour can be encoded in software. An interesting aspect of this work is that the debugger is implemented by means of a program transformation. That is, the program which is to be debugged is transformed into a new one, which when evaluated, behaves like the original program but also produces the evaluation tree as a side-effect. The transformed program is augmented with code to perform the error diagnosis on the tree. Running the transformed program constitutes the evaluation of the original program plus a debugging