Copyright | (c) 2000 Andy Gill, (c) 2010 University of Kansas, (c) 2013-2014 Maarten Faddegon |
---|---|
License | BSD3 |
Maintainer | hoed@maartenfaddegon.nl |
Stability | experimental |
Portability | POSIX |
Safe Haskell | None |
Language | Haskell2010 |
Hoed is a tracer and debugger for the programming language Haskell. You can trace a program by annotating functions in suspected modules and linking your program against standard profiling libraries.
After running the program a computation tree is constructed and displayed in a
web browser. You can freely browse this tree to get a better understanding of
your program. If your program misbehaves, you can judge the computation
statements in the tree as right
or wrong
according to your intention. When
enough statements are judged the debugger tells you the location of the fault
in your code.
I work on this debugger in the context of my Ph.D. research. Read more about the theory behind Hoed at http://maartenfaddegon.nl/#pub.
To use Hoed on your own program, annotate your program as described below. For best results profiling is enabled and optimization disabled. If you use cabal to build your project, this is be done with:
cabal configure --disable-optimization --enable-profiling
I am keen to hear about your experience with Hoed: where did you find it useful and where would you like to see improvement? You can send me an e-mail at hoed@maartenfaddegon.nl, or use the github issue tracker https://github.com/MaartenFaddegon/hoed/issues.
- observe :: Observable a => String -> a -> a
- runO :: IO a -> IO ()
- printO :: Show a => a -> IO ()
- observeTempl :: String -> Q Exp
- observedTypes :: String -> [Q Type] -> Q [Dec]
- observeCC :: Observable a => String -> a -> a
- observe' :: Observable a => String -> Identifier -> a -> (a, Int)
- data Identifier
- (*>>=) :: Monad m => m a -> (Identifier -> (a -> m b, Int)) -> (m b, Identifier)
- (>>==) :: Monad m => (m a, Identifier) -> (Identifier -> (a -> m b, Int)) -> (m b, Identifier)
- (>>=*) :: Monad m => (m a, Identifier) -> (Identifier -> (a -> m b, Int)) -> m b
- logO :: FilePath -> IO a -> IO ()
- newtype Observer = O (forall a. Observable a => String -> a -> a)
- class Observable a where
- observer :: a -> Parent -> a
- (<<) :: Observable a => ObserverM (a -> b) -> a -> ObserverM b
- thunk :: (a -> Parent -> a) -> a -> ObserverM a
- nothunk :: a -> ObserverM a
- send :: String -> ObserverM a -> Parent -> a
- observeBase :: Show a => a -> Parent -> a
- observeOpaque :: String -> a -> Parent -> a
- debugO :: IO a -> IO [CDS]
- data CDS
- class Generic a
Basic annotations
observe :: Observable a => String -> a -> a Source
Functions which you suspect of misbehaving are annotated with observe and should have a cost centre set. The name of the function, the label of the cost centre and the label given to observe need to be the same.
Consider the following function:
triple x = x + x
This function is annotated as follows:
triple y = (observe "triple" (\x -> {# SCC "triple" #} x + x)) y
To produce computation statements like:
triple 3 = 6
To observe a value its type needs to be of class Observable. We provided instances for many types already. If you have defined your own type, and want to observe a function that takes a value of this type as argument or returns a value of this type, an Observable instance can be derived as follows:
data MyType = MyNumber Int | MyName String deriving Generic instance Observable MyType
The main entry point; run some IO code, and debug inside it.
After the IO action is completed, an algorithmic debugging session is started at
http://localhost:10000/
to which you can connect with your webbrowser.
For example:
main = runO $ do print (triple 3) print (triple 2)
Experimental annotations
observeTempl :: String -> Q Exp Source
observeCC :: Observable a => String -> a -> a Source
observe' :: Observable a => String -> Identifier -> a -> (a, Int) Source
data Identifier Source
(*>>=) :: Monad m => m a -> (Identifier -> (a -> m b, Int)) -> (m b, Identifier) Source
(>>==) :: Monad m => (m a, Identifier) -> (Identifier -> (a -> m b, Int)) -> (m b, Identifier) Source
(>>=*) :: Monad m => (m a, Identifier) -> (Identifier -> (a -> m b, Int)) -> m b Source
The Observable class
O (forall a. Observable a => String -> a -> a) |
class Observable a where Source
Nothing
Observable Bool | |
Observable Char | |
Observable Double | |
Observable Float | |
Observable Int | |
Observable Integer | |
Observable () | |
Observable Dynamic | |
Observable SomeException | |
Observable a => Observable [a] | |
Observable a => Observable (IO a) | |
Observable a => Observable (Maybe a) | |
(Observable a, Observable b) => Observable (a -> b) | |
(Observable a, Observable b) => Observable (Either a b) | |
(Observable a, Observable b) => Observable (a, b) | |
(Ix a, Observable a, Observable b) => Observable (Array a b) | |
(Observable a, Observable b, Observable c) => Observable (a, b, c) | |
(Observable a, Observable b, Observable c, Observable d) => Observable (a, b, c, d) | |
(Observable a, Observable b, Observable c, Observable d, Observable e) => Observable (a, b, c, d, e) |
(<<) :: Observable a => ObserverM (a -> b) -> a -> ObserverM b infixl 9 Source
observeBase :: Show a => a -> Parent -> a Source
observeOpaque :: String -> a -> Parent -> a Source
debugO :: IO a -> IO [CDS] Source
run some code and return the CDS structure (for when you want to write your own debugger).
class Generic a
Representable types of kind *. This class is derivable in GHC with the DeriveGeneric flag on.
Generic Bool | |
Generic Char | |
Generic Double | |
Generic Float | |
Generic Int | |
Generic Ordering | |
Generic () | |
Generic All | |
Generic Any | |
Generic Arity | |
Generic Fixity | |
Generic Associativity | |
Generic [a] | |
Generic (U1 p) | |
Generic (Par1 p) | |
Generic (Maybe a) | |
Generic (ZipList a) | |
Generic (Dual a) | |
Generic (Endo a) | |
Generic (Sum a) | |
Generic (Product a) | |
Generic (First a) | |
Generic (Last a) | |
Generic (Either a b) | |
Generic (Rec1 f p) | |
Generic (a, b) | |
Generic (Const a b) | |
Generic (WrappedMonad m a) | |
Generic (Proxy * t) | |
Generic (K1 i c p) | |
Generic ((:+:) f g p) | |
Generic ((:*:) f g p) | |
Generic ((:.:) f g p) | |
Generic (a, b, c) | |
Generic (WrappedArrow a b c) | |
Generic (M1 i c f p) | |
Generic (a, b, c, d) | |
Generic (a, b, c, d, e) | |
Generic (a, b, c, d, e, f) | |
Generic (a, b, c, d, e, f, g) |