Debugging Haskell by Observing Intermediate Data Structures - PowerPoint PPT Presentation

1 / 30
About This Presentation
Title:

Debugging Haskell by Observing Intermediate Data Structures

Description:

by Observing Intermediate Data Structures. Andy Gill. Galois ... Debugging Haskell by Observing Intermediate Data Structures. Debugging any program... – PowerPoint PPT presentation

Number of Views:70
Avg rating:3.0/5.0
Slides: 31
Provided by: andy162
Category:

less

Transcript and Presenter's Notes

Title: Debugging Haskell by Observing Intermediate Data Structures


1
Debugging Haskell by Observing Intermediate Data
Structures
  • Andy Gill
  • Galois Connections
  • andy_at_galconn.com
  • www.cse.ogi.edu/andy

2
Debugging any program
  • Debugging is locating a misunderstanding
  • Finding the difference between
  • What you told the computer to do
  • What you think you told the computer to do
  • Involves running code
  • Sometimes about finding out what someone else
    told the computer to do
  • A Debugger must never, never lie
  • You are gathering evidence, the debugger is under
    oath

3
Traditional debugging tools
  • The printf debuggers
  • Insert printf statements into code
  • Generally the dump and inspect approach
  • Written Statements
  • CLI or GUI Interactive Debuggers
  • GDB
  • Visual Studio
  • Witnesses

4
Tracer Debuggers
  • Trace reduction steps, producing extra output
  • Present dynamically the internal reduction graph
  • Two ways of getting the trace both compiler
    specific
  • Instrumenting the code via transformations
  • Use a modified internal reduction interpreter
  • There is another way ?
  • Two major technical problems
  • The size of the traces can be huge
  • The structures that the user might browse are
    also huge

5
Algorithmic Debugging
  • Also called declarative debugging
  • Semi-automated binary search
  • The system asks Yes/No questions, starting at
    main
  • If a function is giving incorrect results
  • One of the sub functions must be faulty
  • Or this function must be faulty
  • Can use oracles to good effect
  • Expensive asserts
  • Strange interactions with IO

6
Work on Haskell Debuggers
  • Tracing
  • ART/HAT project York (nhc)
  • HOOD OGI
  • GHood, HOOD in NHC, HOOD in Hugs.
  • Declarative
  • Freja Hendrik Nilsson
  • Budda Melbourne, Australia
  • Testing Frameworks
  • Quickcheck Chalmers
  • Auburn York
  • Look at www.haskell.org/debugging

7
Understanding Haskell execution
  • natural Int -gt Int
  • natural
  • reverse 
  • . map (mod 10)
  • . takeWhile (/ 0) 
  • . iterate (div 10)
  • Maingt natural 3408
  • 3,4,0,8 Int

8
The Haskell Object Observation Debugger
  • Provide combinators for debugging
  • STG Hugs or GHC or NHC (others will follow)
  • Frustrated Haskell programmer uses combinators to
    annotate their code, and re-runs the program
  • The execution of the Haskell program allows
    observations to be made internally
  • At the termination of the Haskell execution,
    observed structures are displayed to stderr in a
    pretty printed form
  • Think written statements, but not witnesses

9
Using trace for debugging
  • Function called trace
  • trace String -gt a -gt a
  • Print the string to stderr
  • return the second argument
  • All Haskell systems have this function

10
trace can help
  • foo (xxs) (yxs)
  • foo
  • Can rewrite this as
  • foo x y
  • trace (foo show (x,y)) False
    undefined
  • foo (xxs) (yxs)
  • foo

11
Problems with trace
  • Invasive to your code
  • foo (n 1) gt let r foo (n 1)
  • in trace (show(n1,r)) r
  • Evaluation of first argument can cause other
    traces to fire, mid trace.
  • End up with a spaghetti output
  • Perhaps trace should be evaluate its argument?
  • Can change the evaluation order of your program!
  • Very Bad News
  • The best we had until now

12
Our debugging combinator
  • Provide a way of annotating a specific expression
    with a label.
  • observe (Observable a) gt String -gt a -gt a
  • boring observe after
  • . reverse
  • . observe during
  • . reverse
  • . observe before
  • Similar to probe in Hawk, but works over most
    data types.

13
First example
  • Maingt printO (take 2 (observe list 1..10))
  • printO Show a gt a -gt IO ()
  • Opens the debugging context
  • evaluates the argument
  • with possible observations made
  • Closes the debugging context, pretty prints
    observed structures.

( 1  2  _)
14
Second example
  • printO (
  • let lst 1..10
  • lst1 take 2 (observe list lst)
  • in
  • sum (lst lst1)
  • )

( 1  2  _)
15
Annotating natural
  • Add observe annotations to natural, capturing the
    flow between the subcomponents.
  • natural
  • reverse
  • . observe "after map
  • . map (mod 10)
  • . observe "after takeWhile
  • . takeWhile (/ 0)
  • . observe "after iterate
  • . iterate (div 10)
  • Focuses on the intermediate data structures

16
Output from debugging natural
  • -- after iterate (div 10)
  • (3408 340 34 3 0 _)
  • -- after takeWhile (/ 0)
  • ( 3408 340 34 3 )
  • -- after map (mod 10)
  • ( 8 0 4 3 )

17
What can we observe?
  • Base types
  • Int, Char, Integer, Bool, Float, Double, ()
  • Structured Types
  • Tuples, Lists, Maybe, Arrays
  • Exceptions?
  • What about Monads? (List and Maybe are Monads).
  • What about Functions?
  • observe (Observe a,Observe b) gt String -gt (a
    -gt b) -gt a -gt b
  • What does this definition mean?

18
Observing functions
  • A observed function
  • Only called a specific arguments
  • Finite map from argument to result
  • For observational purposes, functions are
  • A set of pairs, representing argument and result
  • Isomorphic to (a,b)
  • Is this a Set or a Bag?
  • We can pretty print in a Haskell like manner

19
Example of function observation
  • Maingt printO (map (observe "null" null)
    ,1..)
  • -- null
  • \ -gt True
  • , \ (_ _) -gt False
  • Shows only the specific invocations used.

20
Example of higher order function observation
  • Maingt printO
  • (observe map null map null ,1..)
  • -- map null
  • \ \ -gt True
  • , \ (_ _) -gt False
  • ( (_ _) )
  • -gt (True False )

21
Debugging natural (again)
  • Now use HO debugging
  • natural
  • . observe reverse reverse
  • . observe "map (mod 10) map (mod 10)
  • . observe "takeWhile (/ 0) takeWhile (/ 0)
  • . observe "iterate (div 10) iterate (div 10)
  • Focus is now what the sub-components do

22
Output from debugging natural
  • -- iterate (div' 10) 
  • \  \ 3408 -gt 340
  •    , \ 340 -gt 34
  •     , \ 34 -gt 3
  •     , \ 3 -gt 0
  •     
  •     3408 -gt (3408  340  34  3  0  _)
  • -- takeWhile (/ 0)
  • \  \ 3408 -gt True
  •   , \ 340 -gt True
  •    , \ 34 -gt True
  •     , \ 3 -gt True
  •     , \ 0 -gt False
  •     
  •      (3408  340  34  3  0  _) -gt ( 3408  340
      34  3  )

23
Bad implementation of observe
  • observe (Show a) gt String -gt a -gt a
  • observe label a
  • trace (label show a) a
  • Weve changed the strictness of the second
    argument
  • Would fail on our natural example, because one of
    the intermediate lists is infinite
  • Needs to be a member of the class Show
  • Functions are not Show-able.

24
How does lazy evaluation work?
Thunk
25
Structural observers
  • class Observer a where
  • observer a -gt (PATH,LABEL) -gt a
  • -- Example for (a,b)
  • instance (Observer a,Observe b) gt Observe (a,b)
    where
  • -- observer (a,b) -gt (PATH,LABEL) -gt (a,b)
  • observer (a,b) (path,label)
  • unsafePerformIO
  • do sendPacket (,) path label
  • return (observer a (1 path,label),
  • observer b (2 path,label))

26
Systematic side effects
  • fst (observe (f x,44))
  • fst (observer (f x,44) cxt)
  • fst (unsafe do tell about tuple
  • return (observe (f x) (1cxt),observe
    44 (2cxt))
  • )
  • -- Im a 2-tuple at path cxt ( _ , _ )
  • fst (observe (f x) (1cxt),observe 44 (2cxt))
  • observe (f x) (1cxt)
  • seq (f x) (unsafe do tell about the
    number
  • return (f x) )
  • unsafe do tell about the number
  • return 99
  • -- Im an 99 at path 1 cxt ( 99 , _ )
  • 99

27
Status and future of HOOD
  • Current Status
  • V0.1 - Available on web www.haskell.org/hood
  • Works with Hugs, GHC, STG Hugs, NHC
  • Handles GHC threads fine
  • Can catch and observe exceptions (errors, C,
    etc).
  • -- list
  • ( 1 2 error boom _ )
  • The Future
  • V0.2 Interactive browser via XML file (already
    in NHCs version)
  • Polymorphic observations (using RTS hooks)
  • Operational semantics for the debugger?
  • Extensions
  • GHOOD Shows trees instead of pretty printed
    Haskell.
  • Quickcheck for showing counterexamples.

28
Conclusions
  • Haskell has something resembling a debugging tool
    that works on real Haskell
  • Type classes can be used to augment a data
    structure evaluation with side-effecting
    functions
  • Observation of non-trivial examples is possible

29
Demo
import Observe n 10 x1 foldr () 0 1..n y1
foldr (observe "Add" ()) 0 (observe "input"
1..n) z1 printO y1 x2 foldl () 0
1..n x3 foldr () 0 (reverse 1..n) y3
foldr () 0 (take 4 (observe "revlist"
(reverse (observe "input"
1..n)))) z3 printO x3 x4 foldl () 0
(reverse 1..n) y4 foldl () 0 (observe
"revlist" (reverse
(observe "input" 1..n))) z4 printO y4
30
Homework
  • Download HOOD
  • Download HOOD documentation ?
  • Investigate the following
  • foldr () 0 1..n
  • foldl () 0 1..n
  • foldr () 0 (reverse 1..n)
  • foldl () 0 (reverse 1..n)
Write a Comment
User Comments (0)
About PowerShow.com