{- | 

Here are fancier versions of Debug.Trace, with these features:

- unsafePerformIO-based for easy usage in pure code, IO code, and program startup code
- reasonably short and memorable function names
- pretty-printing haskell values, with or without colour, using pretty-simple
- enabling/disabling debug output with --debug
- multiple debug verbosity levels, from 1 to 9
- sending debug output to stderr or to a log file
- enabling logging based on program name

The basic "trace" functions print to stderr.
This debug output will be interleaved with the program's normal output, which can be
useful for understanding when code executes.

The "Log" functions log to a file instead.
The need for these is arguable, since a technically savvy user can redirect
stderr output to a log file, eg: @CMD 2>debug.log@.
But here is how they currently work:

The "traceLog" functions log to the program's debug log file,
which is @PROGNAME.log@ in the current directory,
where PROGNAME is the program name returned by @getProgName@.
When using this logging feature you should call @withProgName@ explicitly
at the start of your program to ensure a stable program name,
otherwise it can change to "<interactive>" eg when running in GHCI.
Eg: @main = withProgName "MYPROG" $ do ...@.

The "OrLog" functions can either print to stderr or log to a file.

- By default, they print to stderr.

- If the program name has been set (with @withProgName) to something ending with ".log", they log to that file instead.
  This can be useful for programs which should never print to stderr, eg TUI programs like hledger-ui.

The "At" functions produce output only when the program was run with a 
sufficiently high debug level, as set by a @--debug[=N]@ command line option.
N ranges from 1 (least debug output) to 9 (most debug output),
@--debug@ with no argument means 1.

The "dbgN*" functions are intended to be the most convenient API, to be embedded
at points of interest in your code. They combine the conditional output of "At",
the conditional logging of "OrLog", pretty printing, and short searchable function names.

Parsing the command line, detecting program name, and file logging is done with unsafePerformIO.
If you are working in GHCI, changing the debug level requires editing and reloading this file
(sometimes it's more convenient to add a dbg0 temporarily).

In hledger, debug levels are used as follows:

@
Debug level:  What to show:
------------  ---------------------------------------------------------
0             normal command output only (no warnings, eg)
1             useful warnings, most common troubleshooting info, eg valuation
2             common troubleshooting info, more detail
3             report options selection
4             report generation
5             report generation, more detail
6             input file reading
7             input file reading, more detail
8             command line parsing
9             any other rarely needed / more in-depth info
@

-}

-- Disabled until 0.1.2.0 is released with windows support
-- This module also exports Debug.Trace and the breakpoint package's Debug.Breakpoint.

-- more:
-- http://hackage.haskell.org/packages/archive/TraceUtils/0.1.0.2/doc/html/Debug-TraceUtils.html
-- http://hackage.haskell.org/packages/archive/trace-call/0.1/doc/html/Debug-TraceCall.html
-- http://hackage.haskell.org/packages/archive/htrace/0.1/doc/html/Debug-HTrace.html
-- http://hackage.haskell.org/packages/archive/traced/2009.7.20/doc/html/Debug-Traced.html
-- https://hackage.haskell.org/package/debug

module Hledger.Utils.Debug (
 
   debugLevel

  -- * Tracing to stderr
  ,traceWith
  ,traceAt
  ,traceAtWith
  ,ptrace
  ,ptraceAt
  ,ptraceAtIO

  -- * Logging to PROGNAME.log
  ,traceLog
  ,traceLogAt
  ,traceLogIO
  ,traceLogAtIO
  ,traceLogWith
  ,traceLogAtWith
  ,ptraceLogAt
  ,ptraceLogAtIO

  -- * Tracing or logging based on shouldLog
  ,traceOrLog
  ,traceOrLogAt
  ,ptraceOrLogAt
  ,ptraceOrLogAtIO
  ,traceOrLogAtWith

  -- * Pretty tracing/logging in pure code
  ,dbg0
  ,dbg1
  ,dbg2
  ,dbg3
  ,dbg4
  ,dbg5
  ,dbg6
  ,dbg7
  ,dbg8
  ,dbg9
  ,dbgExit

  -- * Pretty tracing/logging in IO
  ,dbg0IO
  ,dbg1IO
  ,dbg2IO
  ,dbg3IO
  ,dbg4IO
  ,dbg5IO
  ,dbg6IO
  ,dbg7IO
  ,dbg8IO
  ,dbg9IO

  -- * Tracing/logging with a show function
  ,dbg0With
  ,dbg1With
  ,dbg2With
  ,dbg3With
  ,dbg4With
  ,dbg5With
  ,dbg6With
  ,dbg7With
  ,dbg8With
  ,dbg9With

  -- * Re-exports
  -- ,module Debug.Breakpoint
  ,module Debug.Trace

  )
where

import Control.DeepSeq (force)
import Control.Exception (evaluate)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.List hiding (uncons)
-- import Debug.Breakpoint
import Debug.Trace (trace, traceIO, traceShowId)
import Safe (readDef)
import System.Environment (getProgName)
import System.Exit (exitFailure)
import System.IO.Unsafe (unsafePerformIO)

import Hledger.Utils.IO (progArgs, pshow, pshow')

-- | The program name as returned by @getProgName@.
-- It's best to set this explicitly at program startup with @withProgName@,
-- otherwise when running in GHCI (eg) it will change to "<interactive>".
-- Setting it with a ".log" suffix causes some functions below
-- to log instead of trace.
{-# NOINLINE modifiedProgName #-}
modifiedProgName :: String
modifiedProgName :: String
modifiedProgName = forall a. IO a -> a
unsafePerformIO IO String
getProgName

-- | The progam name, with any ".log" suffix removed.
progName :: String
progName :: String
progName =
  if String
".log" forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` String
modifiedProgName
  then forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
drop Int
4 forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse String
modifiedProgName
  else String
modifiedProgName

-- | The programs debug output verbosity. The default is 0 meaning no debug output.
-- The @--debug@ command line flag sets it to 1, or @--debug=N@ sets it to
-- a higher value (the = is required). Uses unsafePerformIO. 
-- When running in GHCI, changing this requires reloading this module.
debugLevel :: Int
debugLevel :: Int
debugLevel = case forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
/=String
"--debug") [String]
progArgs of
               [String
"--debug"]   -> Int
1
               String
"--debug":String
n:[String]
_ -> forall a. Read a => a -> String -> a
readDef Int
1 String
n
               [String]
_             ->
                 case forall a. Int -> [a] -> [a]
take Int
1 forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (String
"--debug" forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) [String]
progArgs of
                   [Char
'-':Char
'-':Char
'd':Char
'e':Char
'b':Char
'u':Char
'g':Char
'=':String
v] -> forall a. Read a => a -> String -> a
readDef Int
1 String
v
                   [String]
_                                   -> Int
0

-- | Trace a value with the given show function before returning it.
traceWith :: (a -> String) -> a -> a
traceWith :: forall a. (a -> String) -> a -> a
traceWith a -> String
f a
a = forall a. String -> a -> a
trace (a -> String
f a
a) a
a

-- | Pretty-trace a showable value before returning it.
-- Like Debug.Trace.traceShowId, but pretty-printing and easier to type.
ptrace :: Show a => a -> a
ptrace :: forall a. Show a => a -> a
ptrace = forall a. (a -> String) -> a -> a
traceWith forall a. Show a => a -> String
pshow

-- | Trace (print to stderr) a string if the global debug level is at
-- or above the specified level. At level 0, always prints. Otherwise,
-- uses unsafePerformIO.
traceAt :: Int -> String -> a -> a
traceAt :: forall a. Int -> String -> a -> a
traceAt Int
level
    | Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level = forall a b. a -> b -> a
const forall a. a -> a
id
    | Bool
otherwise = forall a. String -> a -> a
trace

-- | Trace (print to stderr) a showable value using a custom show function,
-- if the global debug level is at or above the specified level.
-- At level 0, always prints. Otherwise, uses unsafePerformIO.
traceAtWith :: Int -> (a -> String) -> a -> a
traceAtWith :: forall a. Int -> (a -> String) -> a -> a
traceAtWith Int
level a -> String
f a
a = forall a. Int -> String -> a -> a
traceAt Int
level (a -> String
f a
a) a
a

-- | Pretty-print a label and a showable value to the console
-- if the global debug level is at or above the specified level.
-- At level 0, always prints. Otherwise, uses unsafePerformIO.
ptraceAt :: Show a => Int -> String -> a -> a
ptraceAt :: forall a. Show a => Int -> String -> a -> a
ptraceAt Int
level
    | Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level = forall a b. a -> b -> a
const forall a. a -> a
id
    | Bool
otherwise = \String
lbl a
a -> forall a. String -> a -> a
trace (forall a. Show a => Bool -> String -> a -> String
labelledPretty Bool
True String
lbl a
a) a
a
    
-- Pretty-print a showable value with a label, with or without allowing ANSI color.
labelledPretty :: Show a => Bool -> String -> a -> String
labelledPretty :: forall a. Show a => Bool -> String -> a -> String
labelledPretty Bool
allowcolour String
lbl a
a = String
lbl forall a. [a] -> [a] -> [a]
++ String
":" forall a. [a] -> [a] -> [a]
++ String
nlorspace forall a. [a] -> [a] -> [a]
++ forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" [String]
ls'
  where
    ls :: [String]
ls = String -> [String]
lines forall a b. (a -> b) -> a -> b
$ (if Bool
allowcolour then forall a. Show a => a -> String
pshow else forall a. Show a => a -> String
pshow') a
a
    nlorspace :: String
nlorspace | forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
ls forall a. Ord a => a -> a -> Bool
> Int
1 = String
"\n"
              | Bool
otherwise     = forall a. Int -> a -> [a]
replicate (forall a. Ord a => a -> a -> a
max Int
1 forall a b. (a -> b) -> a -> b
$ Int
11 forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> Int
length String
lbl) Char
' '
    ls' :: [String]
ls' | forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
ls forall a. Ord a => a -> a -> Bool
> Int
1 = forall a b. (a -> b) -> [a] -> [b]
map (Char
' 'forall a. a -> [a] -> [a]
:) [String]
ls
        | Bool
otherwise     = [String]
ls

-- | Like ptraceAt, but convenient to insert in an IO monad and
-- enforces monadic sequencing.
ptraceAtIO :: (MonadIO m, Show a) => Int -> String -> a -> m ()
ptraceAtIO :: forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceAtIO Int
level String
label a
a =
  if Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level
  then forall (m :: * -> *) a. Monad m => a -> m a
return ()
  else forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ String -> IO ()
traceIO (forall a. Show a => Bool -> String -> a -> String
labelledPretty Bool
True String
label a
a)

-- | Should the "trace or log" functions output to a file instead of stderr ?
-- True if the program name ends with ".log".
shouldLog :: Bool
shouldLog :: Bool
shouldLog = String
".log" forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` String
modifiedProgName

-- | The debug log file: PROGNAME.log in the current directory.
-- See modifiedProgName.
debugLogFile :: FilePath
debugLogFile :: String
debugLogFile = String
progName forall a. [a] -> [a] -> [a]
++ String
".log"

-- -- | The debug log file: debug.log in the current directory.
-- debugLogFile :: FilePath
-- debugLogFile = "debug.log"

-- | Log a string to the debug log before returning the second argument.
-- Uses unsafePerformIO.
traceLog :: String -> a -> a
traceLog :: forall a. String -> a -> a
traceLog String
s a
x = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  forall a. a -> IO a
evaluate (forall a. NFData a => a -> a
force String
s)  -- to complete any previous logging before we attempt more
  String -> String -> IO ()
appendFile String
debugLogFile (String
s forall a. [a] -> [a] -> [a]
++ String
"\n")
  forall (m :: * -> *) a. Monad m => a -> m a
return a
x

-- | Log a string to the debug log before returning the second argument,
-- if the global debug level is at or above the specified level.
-- At level 0, always logs. Otherwise, uses unsafePerformIO.
traceLogAt :: Int -> String -> a -> a
traceLogAt :: forall a. Int -> String -> a -> a
traceLogAt Int
level String
str
  | Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level = forall a. a -> a
id
  | Bool
otherwise = forall a. String -> a -> a
traceLog String
str

-- | Like traceLog but sequences properly in IO.
traceLogIO :: MonadIO m => String -> m ()
traceLogIO :: forall (m :: * -> *). MonadIO m => String -> m ()
traceLogIO String
s = do
  forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. a -> IO a
evaluate (forall a. NFData a => a -> a
force String
s)  -- to complete any previous logging before we attempt more
  forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ String -> String -> IO ()
appendFile String
debugLogFile (String
s forall a. [a] -> [a] -> [a]
++ String
"\n")

-- | Like traceLogAt, but convenient to use in IO.
traceLogAtIO :: MonadIO m => Int -> String -> m ()
traceLogAtIO :: forall (m :: * -> *). MonadIO m => Int -> String -> m ()
traceLogAtIO Int
level String
str
  | Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level = forall (m :: * -> *) a. Monad m => a -> m a
return ()
  | Bool
otherwise = forall (m :: * -> *). MonadIO m => String -> m ()
traceLogIO String
str

-- | Log a value to the debug log with the given show function before returning it.
traceLogWith :: (a -> String) -> a -> a
traceLogWith :: forall a. (a -> String) -> a -> a
traceLogWith a -> String
f a
a = forall a. String -> a -> a
traceLog (a -> String
f a
a) a
a

-- | Log a string to the debug log before returning the second argument,
-- if the global debug level is at or above the specified level.
-- At level 0, always logs. Otherwise, uses unsafePerformIO.
traceLogAtWith :: Int -> (a -> String) -> a -> a
traceLogAtWith :: forall a. Int -> (a -> String) -> a -> a
traceLogAtWith Int
level a -> String
f a
a = forall a. Int -> String -> a -> a
traceLogAt Int
level (a -> String
f a
a) a
a 

-- | Pretty-log a label and showable value to the debug log,
-- if the global debug level is at or above the specified level. 
-- At level 0, always prints. Otherwise, uses unsafePerformIO.
ptraceLogAt :: Show a => Int -> String -> a -> a
ptraceLogAt :: forall a. Show a => Int -> String -> a -> a
ptraceLogAt Int
level
  | Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level = forall a b. a -> b -> a
const forall a. a -> a
id
  | Bool
otherwise = \String
lbl a
a -> forall a. String -> a -> a
traceLog (forall a. Show a => Bool -> String -> a -> String
labelledPretty Bool
False String
lbl a
a) a
a

-- | Like ptraceAt, but convenient to insert in an IO monad and
-- enforces monadic sequencing.
ptraceLogAtIO :: (MonadIO m, Show a) => Int -> String -> a -> m ()
ptraceLogAtIO :: forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceLogAtIO Int
level String
label a
a =
  if Int
level forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
debugLevel forall a. Ord a => a -> a -> Bool
< Int
level
  then forall (m :: * -> *) a. Monad m => a -> m a
return ()
  else forall (m :: * -> *). MonadIO m => String -> m ()
traceLogIO (forall a. Show a => Bool -> String -> a -> String
labelledPretty Bool
False String
label a
a)

-- Trace or log a string depending on shouldLog,
-- before returning the second argument.
traceOrLog :: String -> a -> a
traceOrLog :: forall a. String -> a -> a
traceOrLog = if Bool
shouldLog then forall a. String -> a -> a
trace else forall a. String -> a -> a
traceLog

-- Trace or log a string depending on shouldLog,
-- when global debug level is at or above the specified level,
-- before returning the second argument.
traceOrLogAt :: Int -> String -> a -> a
traceOrLogAt :: forall a. Int -> String -> a -> a
traceOrLogAt = if Bool
shouldLog then forall a. Int -> String -> a -> a
traceLogAt else forall a. Int -> String -> a -> a
traceAt

-- Pretty-trace or log depending on shouldLog, when global debug level
-- is at or above the specified level.
ptraceOrLogAt :: Show a => Int -> String -> a -> a
ptraceOrLogAt :: forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt = if Bool
shouldLog then forall a. Show a => Int -> String -> a -> a
ptraceLogAt else forall a. Show a => Int -> String -> a -> a
ptraceAt

-- Like ptraceOrLogAt, but convenient in IO.
ptraceOrLogAtIO :: (MonadIO m, Show a) => Int -> String -> a -> m ()
ptraceOrLogAtIO :: forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO = if Bool
shouldLog then forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceLogAtIO else forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceAtIO

-- Trace or log, with a show function, depending on shouldLog.
traceOrLogAtWith :: Int -> (a -> String) -> a -> a
traceOrLogAtWith :: forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith = if Bool
shouldLog then forall a. Int -> (a -> String) -> a -> a
traceLogAtWith else forall a. Int -> (a -> String) -> a -> a
traceAtWith

-- | Pretty-trace to stderr (or log to debug log) a label and showable value,
-- then return it.
dbg0 :: Show a => String -> a -> a
dbg0 :: forall a. Show a => String -> a -> a
dbg0 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
0

-- | Pretty-trace to stderr (or log to debug log) a label and showable value
-- if the --debug level is high enough, then return the value.
-- Uses unsafePerformIO.
dbg1 :: Show a => String -> a -> a
dbg1 :: forall a. Show a => String -> a -> a
dbg1 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
1

dbg2 :: Show a => String -> a -> a
dbg2 :: forall a. Show a => String -> a -> a
dbg2 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
2

dbg3 :: Show a => String -> a -> a
dbg3 :: forall a. Show a => String -> a -> a
dbg3 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
3

dbg4 :: Show a => String -> a -> a
dbg4 :: forall a. Show a => String -> a -> a
dbg4 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
4

dbg5 :: Show a => String -> a -> a
dbg5 :: forall a. Show a => String -> a -> a
dbg5 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
5

dbg6 :: Show a => String -> a -> a
dbg6 :: forall a. Show a => String -> a -> a
dbg6 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
6

dbg7 :: Show a => String -> a -> a
dbg7 :: forall a. Show a => String -> a -> a
dbg7 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
7

dbg8 :: Show a => String -> a -> a
dbg8 :: forall a. Show a => String -> a -> a
dbg8 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
8

dbg9 :: Show a => String -> a -> a
dbg9 :: forall a. Show a => String -> a -> a
dbg9 = forall a. Show a => Int -> String -> a -> a
ptraceOrLogAt Int
9

-- | Like dbg0, but also exit the program. Uses unsafePerformIO.
dbgExit :: Show a => String -> a -> a
dbgExit :: forall a. Show a => String -> a -> a
dbgExit String
label a
a = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg0IO String
label a
a forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall a. IO a
exitFailure

-- | Like dbgN, but convenient to use in IO.
dbg0IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg0IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg0IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
0

dbg1IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg1IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg1IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
1

dbg2IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg2IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg2IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
2

dbg3IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg3IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg3IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
3

dbg4IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg4IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg4IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
4

dbg5IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg5IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg5IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
5

dbg6IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg6IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg6IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
6

dbg7IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg7IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg7IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
7

dbg8IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg8IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg8IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
8

dbg9IO :: (MonadIO m, Show a) => String -> a -> m ()
dbg9IO :: forall (m :: * -> *) a. (MonadIO m, Show a) => String -> a -> m ()
dbg9IO = forall (m :: * -> *) a.
(MonadIO m, Show a) =>
Int -> String -> a -> m ()
ptraceOrLogAtIO Int
9

-- | Like dbgN, but taking a show function instead of a label.
dbg0With :: (a -> String) -> a -> a
dbg0With :: forall a. (a -> String) -> a -> a
dbg0With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
0

dbg1With :: Show a => (a -> String) -> a -> a
dbg1With :: forall a. Show a => (a -> String) -> a -> a
dbg1With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
1

dbg2With :: Show a => (a -> String) -> a -> a
dbg2With :: forall a. Show a => (a -> String) -> a -> a
dbg2With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
2

dbg3With :: Show a => (a -> String) -> a -> a
dbg3With :: forall a. Show a => (a -> String) -> a -> a
dbg3With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
3

dbg4With :: Show a => (a -> String) -> a -> a
dbg4With :: forall a. Show a => (a -> String) -> a -> a
dbg4With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
4

dbg5With :: Show a => (a -> String) -> a -> a
dbg5With :: forall a. Show a => (a -> String) -> a -> a
dbg5With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
5

dbg6With :: Show a => (a -> String) -> a -> a
dbg6With :: forall a. Show a => (a -> String) -> a -> a
dbg6With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
6

dbg7With :: Show a => (a -> String) -> a -> a
dbg7With :: forall a. Show a => (a -> String) -> a -> a
dbg7With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
7

dbg8With :: Show a => (a -> String) -> a -> a
dbg8With :: forall a. Show a => (a -> String) -> a -> a
dbg8With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
8

dbg9With :: Show a => (a -> String) -> a -> a
dbg9With :: forall a. Show a => (a -> String) -> a -> a
dbg9With = forall a. Int -> (a -> String) -> a -> a
traceOrLogAtWith Int
9