<p dir="ltr">I personally prefer the approach in this package:</p>
<p dir="ltr"><a href="https://hackage.haskell.org/package/NoTrace">https://hackage.haskell.org/package/NoTrace</a></p>
<p dir="ltr">You import Debug.Trace when you want traces and switch the import to Debug.NoTrace to disable them.</p>
<p dir="ltr">You could use a similar strategy with verbosity levels; plus you might not even need levels, as this is module-based you don't get the extra noise from other modules.</p>
<p dir="ltr">- nitrix</p>
<div class="gmail_extra"><br><div class="gmail_quote">On Nov 22, 2016 4:11 PM, "Edward Z. Yang" <<a href="mailto:ezyang@mit.edu">ezyang@mit.edu</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello Clinton,<br>
<br>
Just to clarify, you are asking how to toggle traceability on a<br>
per-module (or perhaps per-package) basis?  Because if you're<br>
OK with tracing be a global affair then putting everything in<br>
a package works quite well (you can use a flag to control<br>
whether or not you want to build with or without tracing.)<br>
<br>
Edward<br>
<br>
Excerpts from Clinton Mead's message of 2016-11-23 00:37:57 +1100:<br>
> I've been debugging some Haskell code, including a lot of work on Mutable<br>
> Vectors, so naturally I've found `trace` useful, and in particular<br>
> `traceM`, because it fits in nicely with monadic code.<br>
><br>
> The problem is that unlike `assert`, both `trace` and `traceM` execute<br>
> unconditionally, I can't toggle them with a compiler flag.<br>
><br>
> I could however do something like this in every file I want to do tracing.<br>
><br>
> {-# LANGUAGE CPP #-}<br>
><br>
> #ifdef TRACE<br>
> trace = Debug.Trace.trace<br>
> traceM = Debug.Trace.traceM<br>
> #else<br>
> trace _ = id<br>
> traceM _ = pure ()<br>
> #endif<br>
><br>
> But already, that's a lot of boilerplate.<br>
><br>
> I'd also like to trace based on debug levels. For example, at TRACE level<br>
> 2, only print trace statements at level 1 or 2, but at TRACE level 4, print<br>
> trace statements at level 1, 2, 3 and 4, providing more detail (but more<br>
> noise).<br>
><br>
> This makes the above code even more complex.<br>
><br>
> This wouldn't be a problem if I could put the code in a separate package,<br>
> but I can't, as then whether tracing is on or not depends on the compiler<br>
> settings of the tracing package, not on the calling package, which defeats<br>
> the purpose somewhat.<br>
><br>
> I considered using implicit parameters to quietly pass whether I want<br>
> tracing and at what level into the tracing module, but it seems to be that<br>
> implicit parameters can't be defined at the top level.<br>
><br>
> It gets even more complex. When debugging, I might want to print something<br>
> of type 'a'. Obviously 'a' will need some sort of show method for this to<br>
> work, but outside of debug mode I don't want to restrict my function's<br>
> types to things which are showable. So I considered doing this:<br>
><br>
> #ifdef TRACE<br>
> type DebugShow a = Show a<br>
> debugShow = show<br>
> #else<br>
> type DebugShow a = ()<br>
> debugShow _ = error "DEBUG SHOWING OUTSIDE OF DEBUG MODE"<br>
> #endif<br>
><br>
> And of course, if you're only using `debugShow` as part of an argument to<br>
> `trace`, lazy evaluation will avoid `debugShow` ever being called when<br>
> tracing is not enabled.<br>
><br>
> But put all this together and you've got around a dozen lines of<br>
> boilerplate just to do tracing, without even having tracing levels yet,<br>
> that have to be put in every module you want to use tracing, but don't want<br>
> a whole lot of debug data being spat out in a release compile.<br>
><br>
> Also, adding any other tracing functions just makes this longer.<br>
><br>
> The only approach I can think of so far is to whack this all in a template<br>
> haskell module and add code that splices it all into the current module:<br>
><br>
> e.g.<br>
><br>
> #ifdef TRACE<br>
> $(traceFunctions True)<br>
> #else<br>
> $(traceFunctions False)<br>
> #endif<br>
><br>
> Where `traceFunctions` is a template haskell function that dumps all the<br>
> appropriate functions and type definitions mentioned above (and maybe more)<br>
> at the top level of the calling module.<br>
><br>
> So my questions are:<br>
><br>
> 1. Is there a better way? And<br>
> 2. Has this problem already been solved?<br>
______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div></div>