How to print with line number and stack trace in H

2020-06-22 04:46发布

问题:

I Java I appended this to my print statements and they had a stack trace...

How can we print line numbers to the log in java

public static int getLineNumber() {
    // The second row of the stack trace had the caller file name, etc.
    return Thread.currentThread().getStackTrace()[2];
}

How do I do this is Haskell?

回答1:

One option appears to be the use of a library like loc-th where you can, for example, write an error message with the line information:

{-# LANGUAGE TemplateHaskell #-}
-- app/Main.hs
module Main where

import Debug.Trace.LocationTH

main :: IO ()
main = do
    $failure "Error"
    putStrLn "Hello"

gives me

my-exe: app/Main.hs:10:5-12: Error

It also provides a string which one could look at, in order to determine the line number. However, I'd imagine that's a bit frowned upon, depending on your use-case. For example, I wouldn't want to see this method used to just log line numbers.

There's more on Haskell debugging techniques here.

Honestly, though, maybe this isn't the greatest idea. What are you planning on doing with the line number?



回答2:

I think I found a solution:

Debug.Trace: Functions for tracing and monitoring execution.

traceStack :: String -> a -> a Source

like trace, but additionally prints a call stack if one is available.

In the current GHC implementation, the call stack is only availble if the program was compiled with -prof; otherwise traceStack behaves exactly like trace. Entries in the call stack correspond to SCC annotations, so it is a good idea to use -fprof-auto or -fprof-auto-calls to add SCC annotations automatically.

Since: 4.5.0.0

^ https://hackage.haskell.org/package/base-4.8.2.0/docs/Debug-Trace.html



回答3:

As noted in @user2407038's comment, modern GHC makes a CallStack available via implicit-parameters, see docs at http://haddock.stackage.org/lts-5.2/base-4.8.2.0/GHC-Stack.html#t:CallStack.

You need the extension -XImplicitParams.

Then it's as simple as:

{-# LANGUAGE ImplicitParams #-}
import           GHC.Stack

msgStacktraced :: (?loc :: CallStack) => String -> IO ()
msgStacktraced msg = putStrLn (msg ++ "\n" ++ showCallStack ?loc)