There are a few factors that cause timestats
to not account correctly for the time spent in all branches. Thanks for sharing this example, it has been rather enlightening.
At the moment, either following the execution with traceM
statements or measuring wall clock time in monadic contexts.
I think in the case of the list monad, your implementation is simpler and has the same behavior as mine. With a monad like IO, I would expect it to be subject to the same caveats as in the documentation of Debug.Trace.taceM while mine would not.
However, here’s another example where this trick doesn’t do better than Debug.Trace.traceM
either.
import qualified Control.Monad.Free as Free
main :: IO ()
main = Free.retract $ do
let m = liftIOtoM (putStrLn "a")
m
m
The output is
$ ghc -package base -O Test.hs && ./Test
a
where I wanted
$ ghc -package base -O Test.hs && ./Test
a
a
Probably a
is printed twice only if the bind operation of the monad is not strict on the result of the second argument. In the following program, the printing is executed when forcing the monadic computation to WHNF.
import qualified Control.Monad.Free as Free
main :: IO ()
main = do
let p :: Free.Free IO ()
p = do let m = liftIOtoM (putStrLn "a")
m
m
seq p (return ())
Thanks all. I’m a tad less excited about this trick now