The Hugs 98 User's Guide | ||
---|---|---|
<<< Previous | Hugs-specific language extensions | Next >>> |
This release of Hugs contains support for debugging by observations inspired by the Andy Gill's Hood library:
Andy Gill, Debugging Haskell by Observing Intermediate Data Structures, in Draft Proceedings of the 2000 Haskell Workshop.
The Haskell Object Observation Debugger http://www.haskell.org/hood/.
Hood is a portable Haskell library that implements the combinator
Observable a => observe :: String -> a -> a |
observe tag |
HugsHood uses the same observation model but differs in a number of ways.
It is much faster. This is because HugsHood is implemented within the Hugs evaluator and uses primitive builtin functions. Performance depends upon the volume of observations. More frequent observations incur a higher overhead. As a simple comparison, a test program which executed 1 million reductions and made 250 observations incurred a 625 percent overhead when observations were made with the Hood library but just 10 percent when using HugsHood.
Caveat: When not using observations, the modifications to the evaluator to support HugsHood imposes an overhead of about 6 percent.
It is possible to easily observe arbitrary data structures. HugsHood implements the primitive
observe :: String -> a -> a |
No modification to the program (apart from instrumentation with observe) is required. The Hood library must be invoked using a special IO monadic combinator to ensure that observations are collected and displayed.
There are a number of minor differences in the display format which are a consequence of the Hugs implementation. These are described below.
Modules that use HugsHood combinators must import the module Hugs.Observe. Its only role is to provide the necessary primitive definitions, namely:
primitive observe :: String -> a -> a primitive bkpt :: String -> a -> a primitive setBkpt :: String -> Bool -> IO () |
HugsHood implements breakpoints. A program can be instrumented with the bkpt function. The partial application
bkpt bkpt_name |
p [tag_name]
Print observations made since the computation began. If an observation tag is suppled then only the associated observations will be displayed. Otherwise all observations will be displayed.
c [n]
Continue with program evaluation. With no arguments, evaluation will continue until another active breakpoint is encountered. The optional numeric argument will skip n active breakpoints before stopping.
s bkpt_name
Set a breakpoint.
r [bkpt_name]
Reset a named breakpoint or, if no breakpoint name is supplied, reset all breakpoints.
A breakpoint is by default disabled. It can be enabled by using the s command in the debug breakpoint dialogue, or by using the setBkpt combinator. Clearly at least one breakpoint must be enabled using setBkpt before a breakpoint dialogue can be triggered.
Here is a very simple program using the three combinators.
import Hugs.Observe prog n = do { setBkpt "fib" True; putStr $ show (observe "fun" f n) } f 0 = 1 f n = n * (bkpt "fib" $ observe "fun" f (n-1)) |
Main> prog 4 Break @ fib> p >>>>>>> Observations <<<<<< fun { \ 4 -> _ } Break @ fib> c Break @ fib> p >>>>>>> Observations <<<<<< fun { \ 4 -> _ , \ 3 -> _ } Break @ fib> c 2 Break @ fib> p >>>>>>> Observations <<<<<< fun { \ 4 -> _ , \ 3 -> _ , \ 2 -> _ , \ 1 -> _ } Break @ fib> c 24 (98 reductions, 299 cells) >>>>>>> Observations <<<<<< fun { \ 4 -> 24 , \ 3 -> 6 , \ 2 -> 2 , \ 1 -> 1 , \ 0 -> 1 } 10 observations recorded |
HugsHood uses a similar style of display to Hood, though there are differences. One trivial difference is that Hood reports tags with a leading "--" while HugsHood does not.
Consider now more significant differences.
HugsHood (and Hood) reports lists using the cons operator.
Observe> observe "list" [1..3] [1,2,3] >>>>>>> Observations <<<<<< list (1 : 2 : 3 : []) |
Observe> observe "string" ['a'..'d'] "abcd" >>>>>>> Observations <<<<<< string "abcd" |
Observe> take 2 $ observe "string" ['a'..'d'] "ab" >>>>>>> Observations <<<<<< string "ab..." |
observe "string" "ab..." |
The "_" symbol is used to indicate an unevaluated expression. In Hood all unevaluated expressions will be displayed using "_". In HugsHood, "_" denotes an unevaluated expression, but not all unevaluated expressions are denoted by "_".
For example the expression fst $ observe "pair" (1,2) yields
-- pair (1, _) |
pair ('a','b') |
Another consequence of the HugsHood implementation by pointers rather than Hood's implementation by tracing evaluation is that the strictness behaviour of a function can be masked. Consider the example:
lazy pair = let x = observe "fst" fst pair y = snd pair in (y,x) |
-- fst { \ (1, _) -> 1 } |
fst { \ (1,2) -> 1 } |
The Hugs compiler uses an optimisation when generating code that builds expressions on the heap. If a function definition has the form
f arg1 .. argN = ..... f arg1 .. argM ..... |
For instance consider the expression
observe "fold" foldl (+) 0 [1..3] |
fold { \ primPlusInteger 6 [] -> 6 , \ { \ 3 3 -> 6 } 3 (3 : []) -> 6 , \ { \ 1 2 -> 3 } 1 (2 : 3 : []) -> 6 , \ { \ 0 1 -> 1 } 0 (1 : 2 : 3 : []) -> 6 |
fold { \ { \ 0 1 -> 1 , \ 1 2 -> 3 , \ 3 3 -> 6 } 0 (1 : 2 : 3 : []) -> 6 } |
The root optimisation can be disabled using the -R option. This can be done from the command line or by using :s -R at the Hugs prompt. If you want to compile the prelude definitions without the root optimisation you must invoke Hugs with the -R option.
Testing of execution time with and without the root optimisation for a selection of 23 benchmarks from the nofib suite has been carried out. All but 5 tests resulted in an execution time penalty of less than 3% when running without root optimisation (some even showed a very minor speedup).
Hugs can produce infinite (cyclic) dictionaries when implementing overloading. The observation reporting mechanism does not detect these at present, which leads to a non-terminating report. We plan to address this in a future release.
Please report bugs to Richard Watson, <rwatson@usq.edu.au>
In particular, if the message
Warning: observation sanity counter > 0 |
<<< Previous | Home | Next >>> |
Here documents | Up | Miscellaneous |