Jeremy Cochoy
Jeremy Cochoy

Reputation: 2652

Debugging haskell: Display a function's name at each call

Is there a tool that automatically "marks" some functions so that I can get an approximation of a "call stack".

Actually, I would like to have a behavior similar to the one you get by writing fct = Debug.trace "fct" $ ... without having to add it before each function.

I know that profiling does something similar with -fprof-auto, but I need it to be displayed while the application is running.

Some time, I have infinite loops and having this display could show me immediately which function(s) is faulty. Using hlist and breakpoints isn't really helpfull since you already have to know the name of one of the functions in the cycle.

Upvotes: 12

Views: 778

Answers (2)

mortza bahjat
mortza bahjat

Reputation: 380

I have developed a plugin for GHC 9+ which does just the thing, but not for every function call instead it prints something like CFG to a file named run.out

Here is the link:

https://github.com/moxeed/bug-riper/blob/master/plugin/Instrumentation.hs

Unfortunately, it's not a package and you have to add it manually to your code by fplugin flag in GHC:

common instrumentation
    ghc-options: -fwrite-ide-info
                 -hiedir=.hie
                 -Wall 
                 --fhpc
                 -fplugin=Instrumentation
    build-depends: plugin-lib

By Adding -O0 flag when building your code, it will actually print for every call. just remember to remove it after debugging is finished.

Upvotes: 1

firefrorefiddle
firefrorefiddle

Reputation: 3805

Here is something incredibly ugly ;-), and it only gives you the line number instead of the function name, but I was surprised to find out that it works, so I thought I'd share it. And it's still better than nothing. You can use the C preprocessor just like in good old C days:

{-# LANGUAGE CPP #-}

#define traceLoc trace (__FILE__ ++":"++ show __LINE__)

import Debug.Trace

f 0 = traceLoc $ 1
f n = traceLoc $ g (n-1)
g 0 = traceLoc $ 2
g n = traceLoc $ 2 * f (n-1)    

Now,

*Main> f 3
Test.hs:16
Test.hs:18
Test.hs:16
Test.hs:17
4

Upvotes: 13

Related Questions