traceM and traceShowM

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
23 messages Options
12
Reply | Threaded
Open this post in threaded view
|

traceM and traceShowM

Martijn van Steenbergen-2
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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

p.k.f.holzenspies@utwente.nl
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

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Lennart Augustsson
In reply to this post by Martijn van Steenbergen-2
+1
I use them all the time.

On Fri, Oct 16, 2009 at 3:22 PM, Martijn van Steenbergen
<[hidden email]> 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
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries
>
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Martijn van Steenbergen-2
In reply to this post by Martijn van Steenbergen-2
pepe wrote:
> But traceM will only work on non-lazy monads, such as Either or Maybe.

That's exactly what you expect from a call to trace: if it doesn't get
evaluated, its message isn't output.

Martijn.

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Pepe Iborra-3
In reply to this post by Martijn van Steenbergen-2
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
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Pepe Iborra-3
In reply to this post by Martijn van Steenbergen-2
True,

But debugging Haskell code is a confusing experience already.
The behaviour of these combinators can be counterintuitive.
They don't work for *any* do-block as you put it in your first
email.
Getting them into the base package may in effect
end up driving many Haskell programmers even more confused
when trying to debug some Haskell code.

In any case the documentation should clearly state that
they only work for strict monads and not for any monad.

On 16/10/2009, at 15:37, Martijn van Steenbergen wrote:

> pepe wrote:
>> But traceM will only work on non-lazy monads, such as Either or  
>> Maybe.
>
> That's exactly what you expect from a call to trace: if it doesn't  
> get evaluated, its message isn't output.
>
> Martijn.
>

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Felipe Lessa
In reply to this post by Martijn van Steenbergen-2
Notwithstanding the laziness problem, +1 as well.

--
Felipe.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Evan Laforge
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.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Joachim Breitner-2
In reply to this post by Martijn van Steenbergen-2
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: [hidden email] | ICQ# 74513189 | GPG-Key: 4743206C
  JID: [hidden email] | http://www.joachim-breitner.de/
  Debian Developer: [hidden email]

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

signature.asc (205 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Martijn van Steenbergen-2
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.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Twan van Laarhoven
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
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Ben Franksen
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

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Martijn van Steenbergen-2
In reply to this post by Martijn van Steenbergen-2
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:

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Twan van Laarhoven
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
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Martijn van Steenbergen-2
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.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Ian Lynagh
In reply to this post by Martijn van Steenbergen-2
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

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Sean Leather


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

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Martijn van Steenbergen-2
In reply to this post by Martijn van Steenbergen-2
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
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

Simon Marlow-7
In reply to this post by Martijn van Steenbergen-2
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
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: traceM and traceShowM

p.k.f.holzenspies@utwente.nl
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?

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
12