# Hat - the Haskell Tracer

about

  What is Hat?
  How do I view a trace?
  Compliance with Haskell 98
  Known bugs
  Libraries supported by Hat
  Frequently asked questions
  Copyright and licence information

download/build/install

  Version 2.00 released 1xth June 2002.
  Download Hat
  System requirements
  Build and install instructions
  Configuration options
  Recent changes

user guides

  A simple tutorial introduction:
  (HTML) (TeX) (PostScript) (PDF)
  A more advanced tutorial:
  (not yet available)
  The Hat user manual:
  (HTML) (TeX) (PostScript) (PDF)
  Reference Guide (hat-trans)
  Reference Guide (browsers)

development

  Technical publications
  Known bugs
  Wish list
  Anonymous CVS repository

community

  Mailing list for everything Hat-related
  More general Haskell mailing lists
  Other Haskell systems and resources

If you have any problems, please send a message to the mailing list at hat@haskell.org.

## What is Hat?

Hat is a source-level tracer for Haskell 98, the standard lazy functional programming language. Hat is a tool that gives the user access to otherwise invisible information about a computation.

Note, Hat is now portable: it works with both ghc and nhc98

### What is it good for?

Hat helps locating errors in programs. Furthermore, it is useful for understanding how a (correct) program works, especially for teaching and program maintenance. Hat is not a time or space profiler. Hat can be used for programs that terminate normally, that terminate with an error message or that terminate when interrupted by the programmer.

### How does it work?

Tracing a program with Hat consists of two phases: First the specially compiled program runs as normal, except that additionally a trace is written to file. Second, after the program has terminated, the trace is viewed with a browsing tool. The trace consists of high-level information about the computation. It describes each reduction, that is, the replacements of an instance of a left-hand side of an equation by an instance of its right-hand side, and the relation of the reduction to other reductions. Because the trace describes the whole computation, it is huge. Hat comes with several tools to selectively view the fragments of the trace that are of interest. Each tool shows fragments of the computation in a particular way, highlighting a specific aspect.

## How can I view a trace?

Because the trace describes the whole computation, it is huge. Hat comes with several tools to selectively view the fragments of the trace that are of interest. Each tool shows fragments of the computation in a particular way, highlighting a specific aspect.

All tools show function arguments in evaluated form, more precisely: as far evaluated as the arguments are at the end of the computation. For example, although in a computation the unevaluated expression `(map (+5) [1,2])` might be passed to the function `length`, the tools will show the function application as `length [1+5,2+5]` or `length [_,_]`.

- Hat-observe (inspired by Hood)
  Hat-observe is an interactive tool that shows how top-level functions are used. That is, for a given top-level function name it shows all the arguments with which it is called during the computation, together with the respective results.

  For example, for the computation of the faulty program

      main = let xs :: [Int]
                 xs = [4*2,5 `div` 0,5+6]
             in  print (head xs,last' xs)

      last' (x:xs) = last' xs
      last' [x] = x

  gives the result

      (8, No match in pattern.

  and the hat-observe tool can be used to explore its behaviour as follows:

      $ hat-observe Example

                      hat-observe 2.00    (:h for help, :q to quit)

      hat-observe> main
      1  main = IO (print (8,_|_))
      hat-observe> print
      1  print (8,_|_) = IO (print (8,_|_))
      hat-observe> last'
      1  last' [8,_,_] = _|_
      2  last' [_,_] = _|_
      3  last' [_] = _|_
      4  last' [] = _|_
      hat-observe> :quit
      $

- Hat-trail
  Hat-trail is an interactive tool that enables exploring a computation backwards, starting at the program output or an error message (with which the computation aborted). This is particularly useful for locating an error. You start at the observed faulty behaviour and work backwards towards the source of the error.

  Every reduction replaces an instance of the left-hand side of a program equation by an instance of its right-hand side. The instance of the left-hand side ``creates'' the instance of the right-hand side and is therefore called its parent. With hat-trail you can obtain the parent of any expression.

  (Note: if you cannot see any highlighting in the following diagram, try changing the fixed-width font in your browser to something like Courier text.) Each line of the trail is the parent of the highlighted subexpression directly above it.

      Error: -------------------------------------------------------
      No match in pattern.
      Output: ------------------------------------------------------
      (8,
      Trail: ---------------------- Example.hs line: 2 col: 12 -----
      <- last' []
      <- last' [_]
      <- last' [_,_]
      <- last' [8,_,_]
      <- 4 * 2
      <- xs

  Here, the error message is chosen as the starting point, rather than any of the output. The first trail is therefore `last' []`, because its evaluation caused the error message. The parent of `last' []` is `last' [_]`. The parent of `last' [_]` is `last' [_,_])`, etc. The parent of the subexpression `8` is `4*2` whose parent is `xs`.

- Hat-detect (inspired by Freja)
  Hat-detect is an interactive tool that enables the semi-automatic location of an error in a program by answering a sequence of yes/no questions. Each question asked by hat-detect concerns the reduction of a redex - that is, a function application - to a value. You have to answer yes, if the reduction is correct with respect to your intentions, and no otherwise. After a number of questions hat-detect states which reduction is the cause of the observed faulty behaviour - that is, which function definition is incorrect.

  Example session (y/n answers are given by the user):

      $ hat-detect Example

                      hat-detect 2.0x    (:h for help, :q to quit)

      1  main = IO (print [3,3,3])   ? n
      2  sort [3,2,1] = [3,3,3]   ? n
      3  insert 1 [] = [1]     ? y
      4  insert 2 [1] = [2,2]     ? n
      5  insert 2 [] = [2]     ? y

      Error located!
      Bug found in reduction:   insert 2 [1] = [2,2]

- Hat-stack
  For aborted computations, that is computations that terminated with an error message or were interrupted, hat-stack shows in which function call the computation was aborted. It does so by showing a virtual stack of function calls (redexes). Thus, every function call shown on the stack caused the function call above it. The evaluation of the top stack element caused the error (or during its evaluation the computation was interrupted). The stack shown is virtual, because it does not correspond to the actual runtime stack. The actual runtime stack enables lazy evaluation whereas the virtual stack corresponds to a stack that would be used for eager (strict) evaluation.

  Using the same example program as above, hat-stack shows

      $ hat-stack Example
      Program terminated with error:
          "No match in pattern."
      Virtual stack trace:                     source file/line/col
          (last' [])                            Example.hs   6  16
          (last' (5+6:[]))                      Example.hs   6  16
          (last' ((div 5 0):5+6:[]))            Example.hs   6  16
          (last' (8:(div 5 0):5+6:[]))          Example.hs   4  27
          main                                  Example.hs   2   1
      $

The latest updates to these pages are available on the WWW from `http://www.cs.york.ac.uk/fp/hat/`

This page last modified: 2002.06.11
York Functional Programming Group