Chris Seaton | 21 Jan 17:48 2013

Is traceIO unnecessarily specialised to the IO monad?

I use printf-style debugging a lot, so I am always adding and removing applications of trace. There is the Debug.Trace.traceIO function that makes this easy to do in the IO monad (it just applies hPutStrLn stderr), but is that specialisation to IO unnecessary?

I find myself always using this utility function:

traceM :: (Monad m) => String -> m ()
traceM message = trace message $ return ()

Which can be used to implement traceIO.

traceIO :: String -> IO ()
traceIO = traceM

That way I can traceM in whatever monad I am in. It is easier to add and remove an application of trace, because I do not have to wrap it around something, and I do not have to remember the return. Of course, you are still subject to however your monad chooses to order the execution of these traces, but that is what people expect when using trace.

Would traceM be a wanted addition to Debug.Trace?

Regards,

Chris Seaton

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Henning Thielemann | 21 Jan 17:53 2013
Picon

Re: Is traceIO unnecessarily specialised to the IO monad?


On Mon, 21 Jan 2013, Chris Seaton wrote:

> Would traceM be a wanted addition to Debug.Trace?

You can use printf for generating Strings and show them using plain 
'trace'.
Chris Seaton | 21 Jan 17:58 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

The user can generate the string however they want. The proposed traceM does not duplicate any printf functionality, and neither requires nor prevents the use of printf.

It is more about allowing the user to add trace actions in an arbitrary monad, rather than just the IO monad. If people want to trace in IO, and we think it is worth a function to do that, might they not want to trace in any monad, and it be worth adding a function for that?

Chris


On 21 January 2013 16:53, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:

On Mon, 21 Jan 2013, Chris Seaton wrote:

Would traceM be a wanted addition to Debug.Trace?

You can use printf for generating Strings and show them using plain 'trace'.

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Herbert Valerio Riedel | 21 Jan 18:09 2013
Picon

Re: Is traceIO unnecessarily specialised to the IO monad?

Chris Seaton <chris <at> chrisseaton.com> writes:

> I use printf-style debugging a lot, so I am always adding and removing
> applications of trace. There is the Debug.Trace.traceIO function that makes
> this easy to do in the IO monad (it just applies hPutStrLn stderr), but is
> that specialisation to IO unnecessary?
>
> I find myself always using this utility function:
>
> traceM :: (Monad m) => String -> m ()
> traceM message = trace message $ return ()
>
> Which can be used to implement traceIO.
>
> traceIO :: String -> IO ()
> traceIO = traceM

btw, that wouldn't have the same semantics as the existing
`Debug.Trace.traceIO` which is more or less something similiar to a
`hPutStrLn stderr` whose side-effect gets triggered at monad-execution
time, whereas the side-effect of `traceM` occurs at monad-construction
time; consider the following program:

--8<---------------cut here---------------start------------->8---
import Control.Monad
import Debug.Trace

traceM :: (Monad m) => String -> m ()
traceM message = trace message $ return ()

traceIO' :: String -> IO ()
traceIO' = traceM

main = replicateM_ 5 $ do 
         trace1
         trace2
  where
    trace1 = traceIO' "trace1"
    trace2 = traceIO  "trace2"
--8<---------------cut here---------------end--------------->8---

when run via runghc (or compiled with -O0) for GHC 7.6, this emits

--8<---------------cut here---------------start------------->8---
trace1
trace2
trace2
trace2
trace2
trace2
--8<---------------cut here---------------end--------------->8---

only when using -O1 or -O2 the output results in

--8<---------------cut here---------------start------------->8---
trace1
trace2
trace1
trace2
trace1
trace2
trace1
trace2
trace1
trace2
--8<---------------cut here---------------end--------------->8---

(I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
haven't checked)

cheers,
  hvr
Chris Seaton | 21 Jan 18:41 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

Yes, I suppose that traceIO does not have the semantics I assumed. Still, I think it is useful to have a trace that one can easily insert into an arbitrary monad. Here's how I use it:

--------

import Debug.Trace

main :: IO ()
main = putStrLn $ show foo

foo :: Maybe Int
foo = do
    x <- bar 14
    traceM $ show x
    y <- bar 2
    traceM $ show y
    return $ x + y

bar :: Int -> Maybe Int
bar x = Just $ 2*x

traceM :: (Monad m) => String -> m ()
traceM message = trace message $ return ()

----------

I think it is cleaner and more obvious than without the abstraction. Plus it is very easy to comment out. It is really good for list comprehensions written in do notation, as I often want to peek at intermediate values of those. I know I always add it to my projects, so I thought it may be wanted in base.

As Henning Thielemann said, you can use printf or whatever with it, but I think that is an orthogonal issue.

Regards,

Chris



On 21 January 2013 17:09, Herbert Valerio Riedel <hvr <at> gnu.org> wrote:
Chris Seaton <chris <at> chrisseaton.com> writes:

> I use printf-style debugging a lot, so I am always adding and removing
> applications of trace. There is the Debug.Trace.traceIO function that makes
> this easy to do in the IO monad (it just applies hPutStrLn stderr), but is
> that specialisation to IO unnecessary?
>
> I find myself always using this utility function:
>
> traceM :: (Monad m) => String -> m ()
> traceM message = trace message $ return ()
>
> Which can be used to implement traceIO.
>
> traceIO :: String -> IO ()
> traceIO = traceM

btw, that wouldn't have the same semantics as the existing
`Debug.Trace.traceIO` which is more or less something similiar to a
`hPutStrLn stderr` whose side-effect gets triggered at monad-execution
time, whereas the side-effect of `traceM` occurs at monad-construction
time; consider the following program:

--8<---------------cut here---------------start------------->8---
import Control.Monad
import Debug.Trace

traceM :: (Monad m) => String -> m ()
traceM message = trace message $ return ()

traceIO' :: String -> IO ()
traceIO' = traceM

main = replicateM_ 5 $ do
         trace1
         trace2
  where
    trace1 = traceIO' "trace1"
    trace2 = traceIO  "trace2"
--8<---------------cut here---------------end--------------->8---

when run via runghc (or compiled with -O0) for GHC 7.6, this emits

--8<---------------cut here---------------start------------->8---
trace1
trace2
trace2
trace2
trace2
trace2
--8<---------------cut here---------------end--------------->8---

only when using -O1 or -O2 the output results in

--8<---------------cut here---------------start------------->8---
trace1
trace2
trace1
trace2
trace1
trace2
trace1
trace2
trace1
trace2
--8<---------------cut here---------------end--------------->8---

(I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
haven't checked)

cheers,
  hvr

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Andreas Abel | 21 Jan 23:31 2013
Picon

Re: Is traceIO unnecessarily specialised to the IO monad?

+1.  I also had to define traceM for the same purposes. --Andreas

On 21.01.13 6:41 PM, Chris Seaton wrote:
> Yes, I suppose that traceIO does not have the semantics I assumed.
> Still, I think it is useful to have a trace that one can easily insert
> into an arbitrary monad. Here's how I use it:
>
> --------
>
> import Debug.Trace
>
> main :: IO ()
> main = putStrLn $ show foo
>
> foo :: Maybe Int
> foo = do
>      x <- bar 14
>      traceM $ show x
>      y <- bar 2
>      traceM $ show y
>      return $ x + y
>
> bar :: Int -> Maybe Int
> bar x = Just $ 2*x
>
> traceM :: (Monad m) => String -> m ()
> traceM message = trace message $ return ()
>
> ----------
>
> I think it is cleaner and more obvious than without the abstraction.
> Plus it is very easy to comment out. It is really good for list
> comprehensions written in do notation, as I often want to peek at
> intermediate values of those. I know I always add it to my projects, so
> I thought it may be wanted in base.
>
> As Henning Thielemann said, you can use printf or whatever with it, but
> I think that is an orthogonal issue.
>
> Regards,
>
> Chris
>
>
>
> On 21 January 2013 17:09, Herbert Valerio Riedel <hvr <at> gnu.org
> <mailto:hvr <at> gnu.org>> wrote:
>
>     Chris Seaton <chris <at> chrisseaton.com <mailto:chris <at> chrisseaton.com>>
>     writes:
>
>      > I use printf-style debugging a lot, so I am always adding and
>     removing
>      > applications of trace. There is the Debug.Trace.traceIO function
>     that makes
>      > this easy to do in the IO monad (it just applies hPutStrLn
>     stderr), but is
>      > that specialisation to IO unnecessary?
>      >
>      > I find myself always using this utility function:
>      >
>      > traceM :: (Monad m) => String -> m ()
>      > traceM message = trace message $ return ()
>      >
>      > Which can be used to implement traceIO.
>      >
>      > traceIO :: String -> IO ()
>      > traceIO = traceM
>
>     btw, that wouldn't have the same semantics as the existing
>     `Debug.Trace.traceIO` which is more or less something similiar to a
>     `hPutStrLn stderr` whose side-effect gets triggered at monad-execution
>     time, whereas the side-effect of `traceM` occurs at monad-construction
>     time; consider the following program:
>
>     --8<---------------cut here---------------start------------->8---
>     import Control.Monad
>     import Debug.Trace
>
>     traceM :: (Monad m) => String -> m ()
>     traceM message = trace message $ return ()
>
>     traceIO' :: String -> IO ()
>     traceIO' = traceM
>
>     main = replicateM_ 5 $ do
>               trace1
>               trace2
>        where
>          trace1 = traceIO' "trace1"
>          trace2 = traceIO  "trace2"
>     --8<---------------cut here---------------end--------------->8---
>
>     when run via runghc (or compiled with -O0) for GHC 7.6, this emits
>
>     --8<---------------cut here---------------start------------->8---
>     trace1
>     trace2
>     trace2
>     trace2
>     trace2
>     trace2
>     --8<---------------cut here---------------end--------------->8---
>
>     only when using -O1 or -O2 the output results in
>
>     --8<---------------cut here---------------start------------->8---
>     trace1
>     trace2
>     trace1
>     trace2
>     trace1
>     trace2
>     trace1
>     trace2
>     trace1
>     trace2
>     --8<---------------cut here---------------end--------------->8---
>
>     (I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
>     haven't checked)
>
>     cheers,
>        hvr
>
>
>
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>

--

-- 
Andreas Abel  <><      Du bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.abel <at> ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/
Roman Cheplyaka | 21 Jan 23:40 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

While we're at it, the trace functions I miss are

  \x -> trace x x

and

  \x -> trace (show x) x

Roman

* Andreas Abel <andreas.abel <at> ifi.lmu.de> [2013-01-21 23:31:24+0100]
> +1.  I also had to define traceM for the same purposes. --Andreas
> 
> On 21.01.13 6:41 PM, Chris Seaton wrote:
> >Yes, I suppose that traceIO does not have the semantics I assumed.
> >Still, I think it is useful to have a trace that one can easily insert
> >into an arbitrary monad. Here's how I use it:
> >
> >--------
> >
> >import Debug.Trace
> >
> >main :: IO ()
> >main = putStrLn $ show foo
> >
> >foo :: Maybe Int
> >foo = do
> >     x <- bar 14
> >     traceM $ show x
> >     y <- bar 2
> >     traceM $ show y
> >     return $ x + y
> >
> >bar :: Int -> Maybe Int
> >bar x = Just $ 2*x
> >
> >traceM :: (Monad m) => String -> m ()
> >traceM message = trace message $ return ()
> >
> >----------
> >
> >I think it is cleaner and more obvious than without the abstraction.
> >Plus it is very easy to comment out. It is really good for list
> >comprehensions written in do notation, as I often want to peek at
> >intermediate values of those. I know I always add it to my projects, so
> >I thought it may be wanted in base.
> >
> >As Henning Thielemann said, you can use printf or whatever with it, but
> >I think that is an orthogonal issue.
> >
> >Regards,
> >
> >Chris
> >
> >
> >
> >On 21 January 2013 17:09, Herbert Valerio Riedel <hvr <at> gnu.org
> ><mailto:hvr <at> gnu.org>> wrote:
> >
> >    Chris Seaton <chris <at> chrisseaton.com <mailto:chris <at> chrisseaton.com>>
> >    writes:
> >
> >     > I use printf-style debugging a lot, so I am always adding and
> >    removing
> >     > applications of trace. There is the Debug.Trace.traceIO function
> >    that makes
> >     > this easy to do in the IO monad (it just applies hPutStrLn
> >    stderr), but is
> >     > that specialisation to IO unnecessary?
> >     >
> >     > I find myself always using this utility function:
> >     >
> >     > traceM :: (Monad m) => String -> m ()
> >     > traceM message = trace message $ return ()
> >     >
> >     > Which can be used to implement traceIO.
> >     >
> >     > traceIO :: String -> IO ()
> >     > traceIO = traceM
> >
> >    btw, that wouldn't have the same semantics as the existing
> >    `Debug.Trace.traceIO` which is more or less something similiar to a
> >    `hPutStrLn stderr` whose side-effect gets triggered at monad-execution
> >    time, whereas the side-effect of `traceM` occurs at monad-construction
> >    time; consider the following program:
> >
> >    --8<---------------cut here---------------start------------->8---
> >    import Control.Monad
> >    import Debug.Trace
> >
> >    traceM :: (Monad m) => String -> m ()
> >    traceM message = trace message $ return ()
> >
> >    traceIO' :: String -> IO ()
> >    traceIO' = traceM
> >
> >    main = replicateM_ 5 $ do
> >              trace1
> >              trace2
> >       where
> >         trace1 = traceIO' "trace1"
> >         trace2 = traceIO  "trace2"
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    when run via runghc (or compiled with -O0) for GHC 7.6, this emits
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    only when using -O1 or -O2 the output results in
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    (I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
> >    haven't checked)
> >
> >    cheers,
> >       hvr
> >
> >
> >
> >
> >_______________________________________________
> >Libraries mailing list
> >Libraries <at> haskell.org
> >http://www.haskell.org/mailman/listinfo/libraries
> >
> 
> -- 
> Andreas Abel  <><      Du bist der geliebte Mensch.
> 
> Theoretical Computer Science, University of Munich
> Oettingenstr. 67, D-80538 Munich, GERMANY
> 
> andreas.abel <at> ifi.lmu.de
> http://www2.tcs.ifi.lmu.de/~abel/
> 
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
Isaac Dupree | 22 Jan 00:31 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

On 01/21/2013 05:40 PM, Roman Cheplyaka wrote:
> While we're at it, the trace functions I miss are
>
>    \x -> trace x x
>
> and
>
>    \x -> trace (show x) x

I've defined those two trace functions for debugging my own code as well.
-Isaac
Chris Seaton | 24 Jan 16:14 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

What do you call these functions? I'll put them all into a patch and open a feature request for them all in one go.

Chris


On 21 January 2013 22:40, Roman Cheplyaka <roma <at> ro-che.info> wrote:
While we're at it, the trace functions I miss are

  \x -> trace x x

and

  \x -> trace (show x) x

Roman

* Andreas Abel <andreas.abel <at> ifi.lmu.de> [2013-01-21 23:31:24+0100]
> +1.  I also had to define traceM for the same purposes. --Andreas
>
> On 21.01.13 6:41 PM, Chris Seaton wrote:
> >Yes, I suppose that traceIO does not have the semantics I assumed.
> >Still, I think it is useful to have a trace that one can easily insert
> >into an arbitrary monad. Here's how I use it:
> >
> >--------
> >
> >import Debug.Trace
> >
> >main :: IO ()
> >main = putStrLn $ show foo
> >
> >foo :: Maybe Int
> >foo = do
> >     x <- bar 14
> >     traceM $ show x
> >     y <- bar 2
> >     traceM $ show y
> >     return $ x + y
> >
> >bar :: Int -> Maybe Int
> >bar x = Just $ 2*x
> >
> >traceM :: (Monad m) => String -> m ()
> >traceM message = trace message $ return ()
> >
> >----------
> >
> >I think it is cleaner and more obvious than without the abstraction.
> >Plus it is very easy to comment out. It is really good for list
> >comprehensions written in do notation, as I often want to peek at
> >intermediate values of those. I know I always add it to my projects, so
> >I thought it may be wanted in base.
> >
> >As Henning Thielemann said, you can use printf or whatever with it, but
> >I think that is an orthogonal issue.
> >
> >Regards,
> >
> >Chris
> >
> >
> >
> >On 21 January 2013 17:09, Herbert Valerio Riedel <hvr <at> gnu.org
> ><mailto:hvr <at> gnu.org>> wrote:
> >
> >    Chris Seaton <chris <at> chrisseaton.com <mailto:chris <at> chrisseaton.com>>
> >    writes:
> >
> >     > I use printf-style debugging a lot, so I am always adding and
> >    removing
> >     > applications of trace. There is the Debug.Trace.traceIO function
> >    that makes
> >     > this easy to do in the IO monad (it just applies hPutStrLn
> >    stderr), but is
> >     > that specialisation to IO unnecessary?
> >     >
> >     > I find myself always using this utility function:
> >     >
> >     > traceM :: (Monad m) => String -> m ()
> >     > traceM message = trace message $ return ()
> >     >
> >     > Which can be used to implement traceIO.
> >     >
> >     > traceIO :: String -> IO ()
> >     > traceIO = traceM
> >
> >    btw, that wouldn't have the same semantics as the existing
> >    `Debug.Trace.traceIO` which is more or less something similiar to a
> >    `hPutStrLn stderr` whose side-effect gets triggered at monad-execution
> >    time, whereas the side-effect of `traceM` occurs at monad-construction
> >    time; consider the following program:
> >
> >    --8<---------------cut here---------------start------------->8---
> >    import Control.Monad
> >    import Debug.Trace
> >
> >    traceM :: (Monad m) => String -> m ()
> >    traceM message = trace message $ return ()
> >
> >    traceIO' :: String -> IO ()
> >    traceIO' = traceM
> >
> >    main = replicateM_ 5 $ do
> >              trace1
> >              trace2
> >       where
> >         trace1 = traceIO' "trace1"
> >         trace2 = traceIO  "trace2"
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    when run via runghc (or compiled with -O0) for GHC 7.6, this emits
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    only when using -O1 or -O2 the output results in
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    (I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
> >    haven't checked)
> >
> >    cheers,
> >       hvr
> >
> >
> >
> >
> >_______________________________________________
> >Libraries mailing list
> >Libraries <at> haskell.org
> >http://www.haskell.org/mailman/listinfo/libraries
> >
>
> --
> Andreas Abel  <><      Du bist der geliebte Mensch.
>
> Theoretical Computer Science, University of Munich
> Oettingenstr. 67, D-80538 Munich, GERMANY
>
> andreas.abel <at> ifi.lmu.de
> http://www2.tcs.ifi.lmu.de/~abel/
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Gershom Bazerman | 24 Jan 16:25 2013
Picon

Re: Is traceIO unnecessarily specialised to the IO monad?

+1 I've used all three functions as well (and traceM probably the most).

As for the other two, the names are probably not the best, but I've used these versions:

traceMsgIt :: Show a => String -> a -> a
traceMsgIt msg x = trace (msg++show x++"\n") x

traceIt :: Show a => a -> a
traceIt x = traceMsgIt "\nTraceIt:\n" x

--Gershom

On 1/24/13 10:14 AM, Chris Seaton wrote:
What do you call these functions? I'll put them all into a patch and open a feature request for them all in one go.

Chris


On 21 January 2013 22:40, Roman Cheplyaka <roma <at> ro-che.info> wrote:
While we're at it, the trace functions I miss are

  \x -> trace x x

and

  \x -> trace (show x) x

Roman

* Andreas Abel <andreas.abel <at> ifi.lmu.de> [2013-01-21 23:31:24+0100]
> +1.  I also had to define traceM for the same purposes. --Andreas
>
> On 21.01.13 6:41 PM, Chris Seaton wrote:
> >Yes, I suppose that traceIO does not have the semantics I assumed.
> >Still, I think it is useful to have a trace that one can easily insert
> >into an arbitrary monad. Here's how I use it:
> >
> >--------
> >
> >import Debug.Trace
> >
> >main :: IO ()
> >main = putStrLn $ show foo
> >
> >foo :: Maybe Int
> >foo = do
> >     x <- bar 14
> >     traceM $ show x
> >     y <- bar 2
> >     traceM $ show y
> >     return $ x + y
> >
> >bar :: Int -> Maybe Int
> >bar x = Just $ 2*x
> >
> >traceM :: (Monad m) => String -> m ()
> >traceM message = trace message $ return ()
> >
> >----------
> >
> >I think it is cleaner and more obvious than without the abstraction.
> >Plus it is very easy to comment out. It is really good for list
> >comprehensions written in do notation, as I often want to peek at
> >intermediate values of those. I know I always add it to my projects, so
> >I thought it may be wanted in base.
> >
> >As Henning Thielemann said, you can use printf or whatever with it, but
> >I think that is an orthogonal issue.
> >
> >Regards,
> >
> >Chris
> >
> >
> >
> >On 21 January 2013 17:09, Herbert Valerio Riedel <hvr <at> gnu.org
> ><mailto:hvr <at> gnu.org>> wrote:
> >
> >    Chris Seaton <chris <at> chrisseaton.com <mailto:chris <at> chrisseaton.com>>
> >    writes:
> >
> >     > I use printf-style debugging a lot, so I am always adding and
> >    removing
> >     > applications of trace. There is the Debug.Trace.traceIO function
> >    that makes
> >     > this easy to do in the IO monad (it just applies hPutStrLn
> >    stderr), but is
> >     > that specialisation to IO unnecessary?
> >     >
> >     > I find myself always using this utility function:
> >     >
> >     > traceM :: (Monad m) => String -> m ()
> >     > traceM message = trace message $ return ()
> >     >
> >     > Which can be used to implement traceIO.
> >     >
> >     > traceIO :: String -> IO ()
> >     > traceIO = traceM
> >
> >    btw, that wouldn't have the same semantics as the existing
> >    `Debug.Trace.traceIO` which is more or less something similiar to a
> >    `hPutStrLn stderr` whose side-effect gets triggered at monad-execution
> >    time, whereas the side-effect of `traceM` occurs at monad-construction
> >    time; consider the following program:
> >
> >    --8<---------------cut here---------------start------------->8---
> >    import Control.Monad
> >    import Debug.Trace
> >
> >    traceM :: (Monad m) => String -> m ()
> >    traceM message = trace message $ return ()
> >
> >    traceIO' :: String -> IO ()
> >    traceIO' = traceM
> >
> >    main = replicateM_ 5 $ do
> >              trace1
> >              trace2
> >       where
> >         trace1 = traceIO' "trace1"
> >         trace2 = traceIO  "trace2"
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    when run via runghc (or compiled with -O0) for GHC 7.6, this emits
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    only when using -O1 or -O2 the output results in
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    (I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
> >    haven't checked)
> >
> >    cheers,
> >       hvr
> >
> >
> >
> >
> >_______________________________________________
> >Libraries mailing list
> >Libraries <at> haskell.org
> >http://www.haskell.org/mailman/listinfo/libraries
> >
>
> --
> Andreas Abel  <><      Du bist der geliebte Mensch.
>
> Theoretical Computer Science, University of Munich
> Oettingenstr. 67, D-80538 Munich, GERMANY
>
> andreas.abel <at> ifi.lmu.de
> http://www2.tcs.ifi.lmu.de/~abel/
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________ Libraries mailing list Libraries <at> haskell.org http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Chris Seaton | 25 Jan 17:24 2013

Re: Is traceIO unnecessarily specialised to the IO monad?



On 24 January 2013 15:25, Gershom Bazerman <gershomb <at> gmail.com> wrote:
+1 I've used all three functions as well (and traceM probably the most).

As for the other two, the names are probably not the best, but I've used these versions:

traceMsgIt :: Show a => String -> a -> a
traceMsgIt msg x = trace (msg++show x++"\n") x

traceIt :: Show a => a -> a
traceIt x = traceMsgIt "\nTraceIt:\n" x

--Gershom


On 1/24/13 10:14 AM, Chris Seaton wrote:
What do you call these functions? I'll put them all into a patch and open a feature request for them all in one go.

Chris


On 21 January 2013 22:40, Roman Cheplyaka <roma <at> ro-che.info> wrote:
While we're at it, the trace functions I miss are

  \x -> trace x x

and

  \x -> trace (show x) x

Roman

* Andreas Abel <andreas.abel <at> ifi.lmu.de> [2013-01-21 23:31:24+0100]
> +1.  I also had to define traceM for the same purposes. --Andreas
>
> On 21.01.13 6:41 PM, Chris Seaton wrote:
> >Yes, I suppose that traceIO does not have the semantics I assumed.
> >Still, I think it is useful to have a trace that one can easily insert
> >into an arbitrary monad. Here's how I use it:
> >
> >--------
> >
> >import Debug.Trace
> >
> >main :: IO ()
> >main = putStrLn $ show foo
> >
> >foo :: Maybe Int
> >foo = do
> >     x <- bar 14
> >     traceM $ show x
> >     y <- bar 2
> >     traceM $ show y
> >     return $ x + y
> >
> >bar :: Int -> Maybe Int
> >bar x = Just $ 2*x
> >
> >traceM :: (Monad m) => String -> m ()
> >traceM message = trace message $ return ()
> >
> >----------
> >
> >I think it is cleaner and more obvious than without the abstraction.
> >Plus it is very easy to comment out. It is really good for list
> >comprehensions written in do notation, as I often want to peek at
> >intermediate values of those. I know I always add it to my projects, so
> >I thought it may be wanted in base.
> >
> >As Henning Thielemann said, you can use printf or whatever with it, but
> >I think that is an orthogonal issue.
> >
> >Regards,
> >
> >Chris
> >
> >
> >
> >On 21 January 2013 17:09, Herbert Valerio Riedel <hvr <at> gnu.org
> ><mailto:hvr <at> gnu.org>> wrote:
> >
> >    Chris Seaton <chris <at> chrisseaton.com <mailto:chris <at> chrisseaton.com>>
> >    writes:
> >
> >     > I use printf-style debugging a lot, so I am always adding and
> >    removing
> >     > applications of trace. There is the Debug.Trace.traceIO function
> >    that makes
> >     > this easy to do in the IO monad (it just applies hPutStrLn
> >    stderr), but is
> >     > that specialisation to IO unnecessary?
> >     >
> >     > I find myself always using this utility function:
> >     >
> >     > traceM :: (Monad m) => String -> m ()
> >     > traceM message = trace message $ return ()
> >     >
> >     > Which can be used to implement traceIO.
> >     >
> >     > traceIO :: String -> IO ()
> >     > traceIO = traceM
> >
> >    btw, that wouldn't have the same semantics as the existing
> >    `Debug.Trace.traceIO` which is more or less something similiar to a
> >    `hPutStrLn stderr` whose side-effect gets triggered at monad-execution
> >    time, whereas the side-effect of `traceM` occurs at monad-construction
> >    time; consider the following program:
> >
> >    --8<---------------cut here---------------start------------->8---
> >    import Control.Monad
> >    import Debug.Trace
> >
> >    traceM :: (Monad m) => String -> m ()
> >    traceM message = trace message $ return ()
> >
> >    traceIO' :: String -> IO ()
> >    traceIO' = traceM
> >
> >    main = replicateM_ 5 $ do
> >              trace1
> >              trace2
> >       where
> >         trace1 = traceIO' "trace1"
> >         trace2 = traceIO  "trace2"
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    when run via runghc (or compiled with -O0) for GHC 7.6, this emits
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    only when using -O1 or -O2 the output results in
> >
> >    --8<---------------cut here---------------start------------->8---
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    trace1
> >    trace2
> >    --8<---------------cut here---------------end--------------->8---
> >
> >    (I'm guessing this due to `trace1` being inlined for -O1/-O2 -- but I
> >    haven't checked)
> >
> >    cheers,
> >       hvr
> >
> >
> >
> >
> >_______________________________________________
> >Libraries mailing list
> >Libraries <at> haskell.org
> >http://www.haskell.org/mailman/listinfo/libraries
> >
>
> --
> Andreas Abel  <><      Du bist der geliebte Mensch.
>
> Theoretical Computer Science, University of Munich
> Oettingenstr. 67, D-80538 Munich, GERMANY
>
> andreas.abel <at> ifi.lmu.de
> http://www2.tcs.ifi.lmu.de/~abel/
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________ Libraries mailing list Libraries <at> haskell.org http://www.haskell.org/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Patrick Palka | 25 Jan 17:44 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

Note that traceM won't work correctly for monads that are not strict in the first argument of >>=, e.g. the Identity monad.


For example, this will not print anything: runIdentity $ traceM "test" >> return ()

On Mon, Jan 21, 2013 at 11:48 AM, Chris Seaton <chris <at> chrisseaton.com> wrote:
I use printf-style debugging a lot, so I am always adding and removing applications of trace. There is the Debug.Trace.traceIO function that makes this easy to do in the IO monad (it just applies hPutStrLn stderr), but is that specialisation to IO unnecessary?

I find myself always using this utility function:

traceM :: (Monad m) => String -> m ()
traceM message = trace message $ return ()

Which can be used to implement traceIO.

traceIO :: String -> IO ()
traceIO = traceM

That way I can traceM in whatever monad I am in. It is easier to add and remove an application of trace, because I do not have to wrap it around something, and I do not have to remember the return. Of course, you are still subject to however your monad chooses to order the execution of these traces, but that is what people expect when using trace.

Would traceM be a wanted addition to Debug.Trace?

Regards,

Chris Seaton


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Chris Seaton | 25 Jan 19:16 2013

Re: Is traceIO unnecessarily specialised to the IO monad?

Agreed, but I think that's the behaviour that you expect when tracing, and when you trace in a monad you would expect get the semantics of that monad as well. For example, you may be using traceM to check that your monad has the strictness behaviour that you expect.

I usually use traceM to view temporary values in a list or maybe comprehension, and then the semantics are obvious because I'm tracing a value that is about to be consumed by the next stage in the pipeline.

I could add some notes about it being best applied with certain monads.

Chris


On 25 January 2013 16:44, Patrick Palka <patrick <at> parcs.ath.cx> wrote:
Note that traceM won't work correctly for monads that are not strict in the first argument of >>=, e.g. the Identity monad.

For example, this will not print anything: runIdentity $ traceM "test" >> return ()

On Mon, Jan 21, 2013 at 11:48 AM, Chris Seaton <chris <at> chrisseaton.com> wrote:
I use printf-style debugging a lot, so I am always adding and removing applications of trace. There is the Debug.Trace.traceIO function that makes this easy to do in the IO monad (it just applies hPutStrLn stderr), but is that specialisation to IO unnecessary?

I find myself always using this utility function:

traceM :: (Monad m) => String -> m ()
traceM message = trace message $ return ()

Which can be used to implement traceIO.

traceIO :: String -> IO ()
traceIO = traceM

That way I can traceM in whatever monad I am in. It is easier to add and remove an application of trace, because I do not have to wrap it around something, and I do not have to remember the return. Of course, you are still subject to however your monad chooses to order the execution of these traces, but that is what people expect when using trace.

Would traceM be a wanted addition to Debug.Trace?

Regards,

Chris Seaton


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries

Gmane