[Haskell-cafe] Debug tracing in Haskell

Corentin Dupont corentin.dupont at gmail.com
Tue Nov 22 15:01:56 UTC 2016


PS: adding a new monad transformer to the monad stack just to add log
capacity seems overkill.
what do you guys think?


On Tue, Nov 22, 2016 at 3:58 PM, Corentin Dupont <corentin.dupont at gmail.com>
wrote:

>
> Hi Clinton,
> I've been running into the same problem recently: regularly adding and
> then removing a lot of traces from my code.
>
> Personally I don't like adding conditional compilation/cpp in my code
> (it's quite ugly and difficult to maintain).
> I've been looking into a logging packages: https://hackage.haskell.org/
> package/tinylog-0.14.0/candidate/docs/System-Logger.html
>
> The question is: how to carry around the settings of the logger (i.e. the
> log levels: Warn, Fatal...) in your program?
> I usually structure my programs around a big State monad, that I access
> using Lenses. The log level could be added there.
>
>
>
>
>
> On Tue, Nov 22, 2016 at 2:37 PM, Clinton Mead <clintonmead at gmail.com>
> wrote:
>
>> I've been debugging some Haskell code, including a lot of work on Mutable
>> Vectors, so naturally I've found `trace` useful, and in particular
>> `traceM`, because it fits in nicely with monadic code.
>>
>> The problem is that unlike `assert`, both `trace` and `traceM` execute
>> unconditionally, I can't toggle them with a compiler flag.
>>
>> I could however do something like this in every file I want to do tracing.
>>
>> {-# LANGUAGE CPP #-}
>>
>> #ifdef TRACE
>> trace = Debug.Trace.trace
>> traceM = Debug.Trace.traceM
>> #else
>> trace _ = id
>> traceM _ = pure ()
>> #endif
>>
>> But already, that's a lot of boilerplate.
>>
>> I'd also like to trace based on debug levels. For example, at TRACE level
>> 2, only print trace statements at level 1 or 2, but at TRACE level 4, print
>> trace statements at level 1, 2, 3 and 4, providing more detail (but more
>> noise).
>>
>> This makes the above code even more complex.
>>
>> This wouldn't be a problem if I could put the code in a separate package,
>> but I can't, as then whether tracing is on or not depends on the compiler
>> settings of the tracing package, not on the calling package, which defeats
>> the purpose somewhat.
>>
>> I considered using implicit parameters to quietly pass whether I want
>> tracing and at what level into the tracing module, but it seems to be that
>> implicit parameters can't be defined at the top level.
>>
>> It gets even more complex. When debugging, I might want to print
>> something of type 'a'. Obviously 'a' will need some sort of show method for
>> this to work, but outside of debug mode I don't want to restrict my
>> function's types to things which are showable. So I considered doing this:
>>
>> #ifdef TRACE
>> type DebugShow a = Show a
>> debugShow = show
>> #else
>> type DebugShow a = ()
>> debugShow _ = error "DEBUG SHOWING OUTSIDE OF DEBUG MODE"
>> #endif
>>
>> And of course, if you're only using `debugShow` as part of an argument to
>> `trace`, lazy evaluation will avoid `debugShow` ever being called when
>> tracing is not enabled.
>>
>> But put all this together and you've got around a dozen lines of
>> boilerplate just to do tracing, without even having tracing levels yet,
>> that have to be put in every module you want to use tracing, but don't want
>> a whole lot of debug data being spat out in a release compile.
>>
>> Also, adding any other tracing functions just makes this longer.
>>
>> The only approach I can think of so far is to whack this all in a
>> template haskell module and add code that splices it all into the current
>> module:
>>
>> e.g.
>>
>> #ifdef TRACE
>> $(traceFunctions True)
>> #else
>> $(traceFunctions False)
>> #endif
>>
>> Where `traceFunctions` is a template haskell function that dumps all the
>> appropriate functions and type definitions mentioned above (and maybe more)
>> at the top level of the calling module.
>>
>> So my questions are:
>>
>> 1. Is there a better way? And
>> 2. Has this problem already been solved?
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>> Only members subscribed via the mailman list are allowed to post.
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20161122/b6f33e8f/attachment.html>


More information about the Haskell-Cafe mailing list