
Hat - The Haskell Tracer
Hat is a source-level tracer for Haskell. It is a tool that gives
the user access to otherwise invisible information about a computation.
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.
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 tool.
Hat can be used for programs that terminate normally, that terminate
with an error message or that terminate when interrupted by the
programmer.
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.
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-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). So every function
call 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 shown stack 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.
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
hat-stack shows
Program terminated with error:
"No match in pattern."
Virtual stack trace:
(last' []) (Example.hs: line-6/col-16)
(last' (5+6:[])) (Example.hs: line-6/col-16)
(last' ((div 5 0):5+6:[])) (Example.hs: line-6/col-16)
(last' (8:(div 5 0):5+6:[])) (Example.hs: line-4/col-27)
main (Example.hs: line-2/col-1)
- Hat-observe (inspired by Hood)
Hat-observe shows a top-level function. That is, for a given top-level
function name it shows all the arguments with which is was called
during the computation together with the respective results.
For example,
hat-observe "last'" Example
shows
last' (8:_:_:[]) = _|_
last' (_:_:[]) = _|_
last' (_:[]) = _|_
last' [] = _|_
- Hat-detect (inspired by Freja)
Hat-detect is an interactive tool that enables locating
semi-automatically 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):
1> main = IO (print (3:3:3:[])) (Y/?/N): n
2> sort (3:2:1:[]) = 3:3:3:[] (Y/?/N): n
3> insert 1 [] = 1:[] (Y/?/N): y
4> insert 2 (1:[]) = 2:2:[] (Y/?/N): n
5> insert 2 [] = 2:[] (Y/?/N): y
Error located!
Bug found: "insert 2 (1:[]) = 2:2:[]"
- 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 an expression.
last' [] is the starting point, because its evaluation
caused an error message. The parent of last' [] is
last' (5+6:[]). The parent of last' (5+6:[])
is last' (5 `div` 0:5+6:[]), etc. The parent of the
subexpression 8 is 4*2 whose parent is
xs.
Documentation
Current Release
Hat 1.10 is part of the Haskell system nhc98. So you get Hat by
downloading nhc98.
-
Download and install nhc98 including Hat
-
How complete is Hat? - a feature summary.
-
Limitations and known bugs.
Please mail bug reports to nhc-bugs@haskell.org.
Development
The ART project
ART (Advanced Redex Trails) is an EPSRC project (started 1st March
2000) to develop a tracer/debugger for Haskell programs.
Hat is developed within the ART project.
The ART project team has the following active members:
Colin Runciman,
Malcolm Wallace,
Olaf Chitil,
Thorsten Brehm and
Phil Hassall.
ART builds on previous work by Colin and
Jan Sparud.
Plans for Future Releases
The ART project proposal describes well
our main aims. Note that details have changed and will continue to change.
Aims for the near future are:
- Enable Hat to trace all Haskell 98 programs (nearly reached).
- Improve speed of traced programs.
- Obtain a tracing pre-processor for other Haskell compilers by separating Hat from nhc98.
- Improve trace viewers (new features; new viewers; integration of viewers)
Support Hat!
You can help us to make Hat a valuable tool for all programmers. Give us
feedback! Starting with bug reports you can tell us what you consider
as Hat's major deficiencies and which improvements would benefit you
most. Thus you may influence our priorities and contribute new ideas.
We are especially looking for medium sized programs (300-3000 lines)
for testing and evaluating Hat. Please
contact us if you want to
contribute a program.
Mailing lists
Because Hat is currently part of nhc98, the nhc mailing lists are the forum for discussing Hat.
To join mailing lists, go to the
haskell.org mailing list
manager.
Publications
- Malcolm Wallace, Olaf Chitil, Thorsten Brehm, and Colin Runciman:
Multiple-View Tracing for Haskell: a New Hat
Proceedings of the
Haskell Workshop 2001, Firenze, Italy.
Different tracing systems for Haskell give different views of a program
at work. In practice, several views are complementary and can productively be
used together. Until now each system has generated its own trace,
containing only the information needed for its particular view.
Here we present the design of a trace that can serve several views.
The trace is generated and written to file as the computation proceeds.
We have implemented both the generation of the trace and several
different viewers.
Postscript (106 KB)
- Olaf Chitil, Colin Runciman and Malcolm Wallace:
Freja, Hat and Hood - A Comparative Evaluation of Three Systems for Tracing and Debugging Lazy Functional Programs
Markus Mohnen and Pieter Koopman (eds): Proceedings of the 12th International Workshop on Implementation of Functional Languages, Aachen, Germany, September 4th - 7th 2000, LNCS 2011, 2001, pp. 176-193.
In this paper we compare three systems for tracing and debugging Haskell programs: Freja, Hat and Hood.
We evaluate their usefulness in practice by applying them to a number of moderately complex programs in which errors had deliberately been introduced. We identify the strengths and weaknesses of each system and then form ideas on how the systems can be improved further.
Postscript (84 KB)
The ART project is the successor of an earlier project and builds on its work which is described in the following publications:
- Jan Sparud and Colin Runciman:
Tracing Lazy Functional Computations Using Redex Trails
(PLILP'97)
(.ps.gz)
- Jan Sparud and Colin Runciman:
Complete and Partial Redex Trails of Functional Computations
(IFL'97)
(.ps.gz)
- Jan Sparud:
Tracing and Debugging Lazy Functional Computations
(PhD thesis, 1999)
(.ps.gz)
This page last modified: 18 Oct 2001
York Functional Programming Group