Discussion:
Proposal: Debug.Trace.traceWith
Kris Nuttycombe
7 years ago
Permalink
When using Debug.Trace for debugging, a very common operation is to prefer
to trace only some subset or function of an intermediate result. As a
consequence, I propose adding the following function to Debug.Trace:

traceWith :: (Show b) => (a -> b) -> a -> a
traceWith f a = trace (show $ f a) a

While it's trivial to define, I have found this to be one of the most
useful functions in my trace-based debugging toolkit, hence my proposal
that it be added to base. It generalizes `traceShowId` in a meaningful and
useful fashion.

As this is the first such proposal I've put forth, please let me know if
I'm doing anything wrong with it!

Thanks,

Kris Nuttycombe
Theodore Lief Gannon
7 years ago
Permalink
Hearty +1 one to this. Note:

traceShowId = traceWith id
traceShow = traceWith . const
...
David Feuer
7 years ago
Permalink
Other another bike-shed color:

traceWith :: (a -> String) -> a -> a
traceWith f a = trace (f a) a

traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith f = traceWith (show . f)

But on the other hand, pointfree.io tells me that you can write

trace =<< f
trace =<< show . f

so I'm not sure how urgent these are.

On Feb 9, 2018 8:08 PM, "Kris Nuttycombe" <***@gmail.com> wrote:

When using Debug.Trace for debugging, a very common operation is to prefer
to trace only some subset or function of an intermediate result. As a
consequence, I propose adding the following function to Debug.Trace:

traceWith :: (Show b) => (a -> b) -> a -> a
traceWith f a = trace (show $ f a) a

While it's trivial to define, I have found this to be one of the most
useful functions in my trace-based debugging toolkit, hence my proposal
that it be added to base. It generalizes `traceShowId` in a meaningful and
useful fashion.

As this is the first such proposal I've put forth, please let me know if
I'm doing anything wrong with it!

Thanks,

Kris Nuttycombe
Joachim Breitner
7 years ago
Permalink
Hi,
Post by David Feuer
traceWith :: (a -> String) -> a -> a
traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith f = traceWith (show . f)
so many bike-shed colors! Maybe an indication that not all of them are
needed, but we should rather be better at pointing to useful, concice
and non-obvoius idioms?
Post by David Feuer
But on the other hand, pointfree.io tells me that you can write
trace =<< f
trace =<< show . f
so I'm not sure how urgent these are.
Nifty! If we add this prominently to the docs in Data.Trace, wouldn’t
that suit us better?

Cheers,
Joachim
--
Joachim Breitner
***@joachim-breitner.de
http://www.joachim-breitner.de/
Michael Sloan
7 years ago
Permalink
I often define

tracer prefix x = trace (prefix ++ ": " ++ show x) x

A bit arbitrary with the choice of ": ", but quite convenient. The with
variant would be

tracerWith prefix f x = trace (prefix ++ ": " ++ show (f x)) x

On Feb 9, 2018 5:09 PM, "Kris Nuttycombe" <***@gmail.com> wrote:

When using Debug.Trace for debugging, a very common operation is to prefer
to trace only some subset or function of an intermediate result. As a
consequence, I propose adding the following function to Debug.Trace:

traceWith :: (Show b) => (a -> b) -> a -> a
traceWith f a = trace (show $ f a) a

While it's trivial to define, I have found this to be one of the most
useful functions in my trace-based debugging toolkit, hence my proposal
that it be added to base. It generalizes `traceShowId` in a meaningful and
useful fashion.

As this is the first such proposal I've put forth, please let me know if
I'm doing anything wrong with it!

Thanks,

Kris Nuttycombe
Kris Nuttycombe
7 years ago
Permalink
Post by Michael Sloan
I often define
tracer prefix x = trace (prefix ++ ": " ++ show x) x
I also have `traceWithPrefix :: (Show b) -> String -> (a -> b) -> a -> a`
defined, for the same reason, so I absolutely support adding that as well.
Post by Michael Sloan
A bit arbitrary with the choice of ": ", but quite convenient. The with
variant would be
tracerWith prefix f x = trace (prefix ++ ": " ++ show (f x)) x
The definition I use is simply

traceWithPrefix p f a = trace (p ++ show (f a)) a
Post by Michael Sloan
traceWith :: (a -> String) -> a -> a
traceWith f a = trace (f a) a
traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith f = traceWith (show . f)
Is there some situation where the `Show String` instance wouldn't be in
scope? If `b` is `String` it works out just fine, so the first definition
you gave here seems superfluous.
Post by Michael Sloan
But on the other hand, pointfree.io tells me that you can write
trace =<< f
trace =<< show . f
That's... remarkably clever, so clever that it never occurred to me in 4
years of writing Haskell. :) I see your point, but jumping to the `Monad
Reader` instance is a bit surprising. At very least, maybe this approach
ought to be documented in the module. Thanks for pointing it out!

So, a question for all: if I were to want to create a pull request to add
these functions (traceWith and traceWithPrefix) where would I go to do so?

Thanks,

Kris
...
David Feuer
7 years ago
Permalink
Post by David Feuer
traceWith :: (a -> String) -> a -> a
traceWith f a = trace (f a) a
traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith f = traceWith (show . f)
Is there some situation where the `Show String` instance wouldn't be in
scope? If `b` is `String` it works out just fine, so the first definition
you gave here seems superfluous.


If the strings have non-ASCII characters, show will mangle them.
David Feuer
7 years ago
Permalink
Also, if you're pretty-printing something to use with trace, show will
knock off the alignment and such.
Post by Kris Nuttycombe
Post by David Feuer
traceWith :: (a -> String) -> a -> a
traceWith f a = trace (f a) a
traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith f = traceWith (show . f)
Is there some situation where the `Show String` instance wouldn't be in
scope? If `b` is `String` it works out just fine, so the first definition
you gave here seems superfluous.
If the strings have non-ASCII characters, show will mangle them.
Kris Nuttycombe
7 years ago
Permalink
Ah, that makes sense, I forgot about the escaping issues.
Post by Kris Nuttycombe
Post by David Feuer
traceWith :: (a -> String) -> a -> a
traceWith f a = trace (f a) a
traceShowWith :: Show b => (a -> b) -> a -> a
traceShowWith f = traceWith (show . f)
Is there some situation where the `Show String` instance wouldn't be in
scope? If `b` is `String` it works out just fine, so the first definition
you gave here seems superfluous.
If the strings have non-ASCII characters, show will mangle them.
Loading...