
Hello, I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
These functions allow tracing in any do-block. I often define them myself; I think they are useful in general. Deadline: 23 October 2009. Martijn.

On Fri, 2009-10-16 at 15:22 +0200, Martijn van Steenbergen wrote:
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
I gladly second this proposal! Philip

+1
I use them all the time.
On Fri, Oct 16, 2009 at 3:22 PM, Martijn van Steenbergen
Hello,
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
These functions allow tracing in any do-block. I often define them myself; I think they are useful in general.
Deadline: 23 October 2009.
Martijn. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

But traceM will only work on non-lazy monads, such as Either or Maybe. On lazy monads, such as the lazy variants of State, Reader and Writer, you would need to write do {() <- traceM msg; ... } to ensure that the trace statement is output. Prelude> :set -fno-monomorphism-restriction Prelude> let m = do { traceM "hola" ; return 6} Prelude> m hola 6 Prelude> Data.Maybe.fromJust m hola 6 Prelude> head m hola 6 Prelude> Control.Monad.State.evalState m () 6 Cheers pepe On 16/10/2009, at 15:22, Martijn van Steenbergen wrote:
Hello,
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ()) traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
These functions allow tracing in any do-block. I often define them myself; I think they are useful in general.
Deadline: 23 October 2009.
Martijn. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Nice, the traceM here would help reduce the "hunt for a place to tack the trace" game. As an aside, I have the following defined, which I use much more frequently than plain trace: tracem msg x = Trace.trace ("**" ++ msg ++ ": " ++ show x) x The 'm' has nothing to do with monads, it's just a short name.

Hi, Am Freitag, den 16.10.2009, 15:22 +0200 schrieb Martijn van Steenbergen:
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
thanks to your mail I found out about traceShow. This does save some time, but I still find myself inserting (\x -> trace (show x) x) or now (\x -> traceShow x x) into chained functions. If Debug.Trace, Control.Monad.Instances and Control.Monad happend to be in scope, this can be abbreviated by join traceShow :: (Show a) => a -> a but maybe with a good name, this would be useful in Debug.Trace directly? I’d really appreciate such a function when debugging code written in points-free style. Greetings, Joachim -- Joachim "nomeata" Breitner mail: mail@joachim-breitner.de | ICQ# 74513189 | GPG-Key: 4743206C JID: nomeata@joachim-breitner.de | http://www.joachim-breitner.de/ Debian Developer: nomeata@debian.org

Joachim Breitner wrote:
join traceShow :: (Show a) => a -> a
Yes, you're right. I rarely use trace directly. I either use traceM, join trace or join traceShow. I can't think of good names for these last two functions, though. But if someone else can, I'm all in favour. Thanks, Martijn.

Martijn van Steenbergen wrote:
Joachim Breitner wrote:
join traceShow :: (Show a) => a -> a
Yes, you're right. I rarely use trace directly. I either use traceM, join trace or join traceShow. I can't think of good names for these last two functions, though. But if someone else can, I'm all in favour.
Perhaps traceShow should have had type (Show a) => a -> a, but assuming we don't want to remove existing functions, how about withTrace :: (Show a) => a -> a withTrace x = trace (show x) x and perhaps withTraceMsg :: (Show a) => String -> a -> a withTraceMsg msg x = trace (msg ++ ": " ++ show x) x -- not sure about formating I'm not sure about a monadic variant of withTrace, what type should it have? Twan

Twan van Laarhoven wrote:
Martijn van Steenbergen wrote:
Joachim Breitner wrote:
join traceShow :: (Show a) => a -> a
Yes, you're right. I rarely use trace directly. I either use traceM, join trace or join traceShow. I can't think of good names for these last two functions, though. But if someone else can, I'm all in favour.
Perhaps traceShow should have had type (Show a) => a -> a, but assuming we don't want to remove existing functions, how about
withTrace :: (Show a) => a -> a withTrace x = trace (show x) x
and perhaps
withTraceMsg :: (Show a) => String -> a -> a withTraceMsg msg x = trace (msg ++ ": " ++ show x) x -- not sure about formating
+1 these are good names (and very useful functions that everyone using Debug.trace has implemented for themselves at least once). Cheers Ben

So the current idea is:
withTrace :: Show a => a -> a withTrace x = trace (show x) x
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
I'm not too good at writing documentation, so if someone would like to do that, please go ahead. Does anyone have anything else to add? Martijn. Martijn van Steenbergen wrote:
I propose the addition of the following two functions to module Debug.Trace:

Martijn van Steenbergen wrote:
So the current idea is:
withTrace :: Show a => a -> a withTrace x = trace (show x) x
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
I'm not too good at writing documentation, so if someone would like to do that, please go ahead.
-- | When called, 'withTrace' prints its argument before returning it. withTrace :: Show a => a -> a -- | When called, 'traceM' outputs the string in its first argument, before returning @()@. This function is intended for tracing in a do-block. -- -- Note: In non-strict monads you need to write -- -- > do () <- traceM msg -- -- to ensure that the trace message is output. traceM :: Monad m => String -> m () -- | Like 'traceM', but uses 'show' on the argument to convert it to a 'String'. -- -- > traceShowM = traceM . show traceShowM :: (Show a, Monad m) => a -> m () ------------------------------- While we are at it, there should also be some module documentation. Right now it just says "The 'trace' function." -- -- The 'trace' function is intended for printing debug messages. -- Using 'trace', a message is printed as a side effect of evaluating an expression. -- -- Example: -- -- > fib 0 = trace "base 0" 1 -- > fib 1 = trace "base 1" 1 -- > fib n = trace ("fib "++show n) $ fib (n-1) + fib (n-2) -- -- Depending on the evaluation order, calculating @fib 3@ might output -- -- > fib 3 -- > fib 2 -- > base 1 -- > base 0 -- > out 2 -- > base 1 -- > out 3 -- I don't know whether adding an example is a good idea, or if it would just distract users. ------------------------------- While writing the above example, another thing just occured to me: it should be possible for trace and withTrace to bracket the computation. What I mean by that is something like bracketTrace a1 a2 b = trace a1 (b `seq` trace a2 b) Or separately: -- | When called, 'traceOut' first evaluates its second argument, -- then prints a message, and finally returns the second argument. traceOut :: String -> a -> a traceOut a b = b `seq` trace a b Perhaps we can use some global state to keep track of nested trace calls, so the above example would output fib 3 fib 2 base 1 base 0 base 1 Twan

Twan van Laarhoven wrote:
-- | When called, 'withTrace' prints its argument before returning it.
I think we should get rid of any occurrences of 'When called' because it is implied.
Depending on the evaluation order, calculating @fib 3@ might output
'Depending on the evaluation order' makes it sound it might be different from time to time which I don't think is true. Other than that I like what you wrote and I'm a big fan of the Fibonacci example. :-) Martijn.

On Wed, Oct 21, 2009 at 09:36:55AM +0200, Martijn van Steenbergen wrote:
So the current idea is:
withTrace :: Show a => a -> a withTrace x = trace (show x) x
Does anyone have anything else to add?
I would expect withTrace :: Show a => String -> a -> a withTrace str x = trace (str ++ show x) x to be more useful. Thanks Ian

On Thu, Oct 22, 2009 at 19:44, Ian Lynagh wrote:
On Wed, Oct 21, 2009 at 09:36:55AM +0200, Martijn van Steenbergen wrote:
So the current idea is:
withTrace :: Show a => a -> a withTrace x = trace (show x) x
Does anyone have anything else to add?
I would expect
withTrace :: Show a => String -> a -> a withTrace str x = trace (str ++ show x) x
to be more useful.
I agree. It's easy enough to do withTrace "" if you don't want a message. Sean

I have submitted a trac ticket: http://hackage.haskell.org/trac/ghc/ticket/3634 Thank you all for your input! Martijn. Martijn van Steenbergen wrote:
Hello,
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
These functions allow tracing in any do-block. I often define them myself; I think they are useful in general.
Deadline: 23 October 2009.
Martijn. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 16/10/2009 14:22, Martijn van Steenbergen wrote:
Hello,
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
is traceShowM really necessary? It doesn't save many characters, and fails the "don't name a composition" test. Cheers, Simon

On Wed, 2009-11-04 at 15:40 +0000, Simon Marlow wrote:
On 16/10/2009 14:22, Martijn van Steenbergen wrote:
Hello,
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
is traceShowM really necessary? It doesn't save many characters, and fails the "don't name a composition" test.
As a post-deadline suggestion to fix Simon's (valid) reservation: traceShowM :: (Show a, Monad m) => a -> m a traceShowM a = traceM (show a) a This allows easier trace insertion, e.g.: foo a = do x <- bar a y <- frop x becomes foo a = do x <- bar a >>= traceShowM y <- frop x >>= traceShowM This, to me, looks like a nice syntactic solution. Regards, Philip PS. Is there some seq/deep_seq/strict/whatever solution for the lazy monads problem hiding in here somewhere?

Philip K.F. Hölzenspies wrote:
As a post-deadline suggestion to fix Simon's (valid) reservation:
traceShowM :: (Show a, Monad m) => a -> m a traceShowM a = traceM (show a) a
This allows easier trace insertion, e.g.:
I disagree. I think it's easier to remove/comment/uncomment (which you do often with trace statements) a whole line than part of a line. On the other hand, you can still use this function as a standalone line. But I don't like having monadic functions return something when that's not necessary, even though I cannot think of a clear argument against it at the moment. :-( So I guess either way is fine. Does anyone else know any criteria to decide one way or another? Martijn.

Simon Marlow wrote:
On 16/10/2009 14:22, Martijn van Steenbergen wrote:
Hello,
I propose the addition of the following two functions to module Debug.Trace:
traceM :: Monad m => String -> m () traceM msg = trace msg (return ())
traceShowM :: (Show a, Monad m) => a -> m () traceShowM = traceM . show
is traceShowM really necessary? It doesn't save many characters, and fails the "don't name a composition" test.
No, it's not necessary at all. There's a bit of tension between not wanting to name a composition and being consistent with the rest of the module: traceM and traceShowM mirror the existing trace and traceShow functions. Martijn.
participants (12)
-
Ben Franksen
-
Evan Laforge
-
Felipe Lessa
-
Ian Lynagh
-
Joachim Breitner
-
Lennart Augustsson
-
Martijn van Steenbergen
-
pepe
-
Philip K.F. Hölzenspies
-
Sean Leather
-
Simon Marlow
-
Twan van Laarhoven