This question already has an answer here:
How can I figure out the line number where exception occured in Haskell?
(1 answer)
Closed 1 year ago.
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?
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?
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
As noted in #user2407038's comment, modern GHC makes a CallStack available, see docs at https://www.stackage.org/haddock/lts-17.13/base-4.14.1.0/GHC-Stack.html#t:HasCallStack
Print the callstack like this:
import GHC.Stack
msgStacktraced :: HasCallStack => String -> IO ()
msgStacktraced msg = putStrLn (msg ++ "\n" ++ prettyCallStack callStack)
You'll need that HasCallStack constraint on anything that can call msgStacktraced as well, or it'll be hidden from the call stack.
Related
Coming from Haskell, I'm accustomed to using it to refer to the result of the previous command in GHCi:
ghci> 1+1
2
ghci> :type it
it :: Num a => a
ghci> it*2
4
I went looking to see if there was something similar in the PureScript REPL, but I couldn't find anything about it on the "Differences from Haskell" page in the PureScript docs (which makes a certain kind of sense now that I've had some time to think about it, since it is a specific feature of GHCi, not of the Haskell language itself), or in the PSCi documentation. In GHCi I can :show bindings to discover that it has been bound, but PSCi's :show command doesn't accept the bindings argument, and from the built-in PSCi help :? it's not obvious to me if there's a different command that does the same thing. (I know PSCI's :browse lets you examine the functions from a specific module, so since errors reported in PSCi often begin with Error found: in module $PSCI I tried :browse $PSCI, but this produces an indentation error.)
Some errors I've encountered seem to suggest that PSCi is trying to bind the result of a computation to the name it (I've cut some whitespace but otherwise this is copied verbatim from a fresh spago repl session in a toy project—note the final line, in value declaration it):
> import Prelude
> 1+'a'
Error found:
in module $PSCI
at :1:3 - 1:6 (line 1, column 3 - line 1, column 6)
Could not match type
Char
with type
Int
while checking that type Char
is at least as general as type Int
while checking that expression 'a'
has type Int
in value declaration it
But after a successful computation, it isn't available:
> 1+1
2
> it
Error found:
at <internal>:0:0 - 0:0 (line 0, column 0 - line 0, column 0)
The value of it is undefined here, so this reference is not allowed.
This is a CycleInDeclaration error, which is different from the UnknownName error produced when trying to use some other undefined name like x or foo. This all makes me suspect there is something special going on with it and I'm just missing something obvious about how to make it available for use in the REPL, but as someone brand new to PureScript, I'm not sure where to look next.
I have a tricky question;
So, I know that GHC will ‘cache’ (for lack of a better term) top level definitions and only compute them once, e.g. :
myList :: [Int]
myList = fmap (*10) [0..10]
Even if I use myList in several spots, GHC notices the value has no params, so it can share it and won’t ‘rebuild’ the list.
I want to do that, but with a computation which depends on a type-level context; a simplified example is:
dependentList :: forall n. (KnownNat n) => [Nat]
dependentList = [0..natVal (Proxy #n)]
So the interesting thing here, is that there isn’t a ‘single’ cacheable value for dependentList; but once a type is applied it reduces down to a constant, so in theory once the type-checker runs, GHC could recognize that several spots all depend on the ‘same’ dependentList; e.g. (using TypeApplications)
main = do
print (dependentList #5)
print (dependentList #10)
print (dependentList #5)
My question is, will GHC recognize that it can share both of the 5 lists? Or does it compute each one separately? Technically it would even be possible to compute those values at Compile-time rather than run-time, is it possible to get GHC to do that?
My case is a little more complicated, but should follow the same constraints as the example, however my dependentList-like value is intensive to compute.
I’m not at all opposed to doing this using a typeclass if it makes things possible; does GHC cache and re-use typeclass dictionaries? Maybe I could bake it into a constant in the typeclass dict to get caching?
Ideas anyone? Or anyone have reading for me to look at for how this works?
I'd prefer to do this in such a way that the compiler can figure it out rather than using manual memoization, but I'm open to ideas :)
Thanks for your time!
As suggested by #crockeea I ran an experiment; here's an attempt using a top-level constant with a polymorphic ambiguous type variable, and also an actual constant just for fun, each one contains a 'trace'
dependant :: forall n . KnownNat n => Natural
dependant = trace ("eval: " ++ show (natVal (Proxy #n))) (natVal (Proxy #n))
constantVal :: Natural
constantVal = trace "constant val: 1" 1
main :: IO ()
main = do
print (dependant #1)
print (dependant #1)
print constantVal
print constantVal
The results are unfortunate:
λ> main
eval: 1
1
eval: 1
1
constant val: 1
1
1
So clearly it re-evaluates the polymorphic constant each time it's used.
But if we write the constants into a typeclass (still using Ambiguous Types) it appears that it will resolve the Dictionary values only once per instance, which makes sense when you know that GHC passes the same dict for the same class instances. It does of course re-run the code for different instances:
class DependantClass n where
classNat :: Natural
instance (KnownNat n) => DependantClass (n :: Nat) where
classNat = trace ("dependant class: " ++ show (natVal (Proxy #n))) (natVal (Proxy #n))
main :: IO ()
main = do
print (classNat #1)
print (classNat #1)
print (classNat #2)
Result:
λ> main
dependant class: 1
1
1
dependant class: 2
2
As far as getting GHC to do these at compile-time, it looks like you'd do that with lift from TemplateHaskell using this technique.
Unfortunately you can't use this within the typeclass definition since TH will complain that the '#n' must be imported from a different module (yay TH) and it's not known concretely at compile time. You CAN do it wherever you USE the typeclass value, but it'll evaluate it once per lift and you have to lift EVERYWHERE you use it to get the benefits; pretty impractical.
https://www.inf.ed.ac.uk/teaching/courses/inf1/fp/exams/exam-2016-paper1-answers.pdf
-- 3b
trace :: Command -> State -> [State]
trace Nil s = [s]
trace (com :#: mov) s = t ++ [state mov (last t)]
where t = trace com s
I am having troubles to understand section 3b. I try to debug the variables one by one but I always end up with violating the defined data types. The code confuses me and I want to see what the variables contain. How can I do it using Debug.Trace?
https://downloads.haskell.org/~ghc/latest/docs/html/libraries/base-4.12.0.0/Debug-Trace.html
Thank you.
Looks like section 3b is teaching 'How Recursion works' Those slides cover only conventional Haskell Lists. What you have with :#: is the opposite, sometimes called a snoc list. Then a sensible design for trace would be to also produce a snoc list result. But it doesn't (presumably because the lecturer thinks that by torturing beginners like this, they'll learn something). Haskell List comprehensions only work for Lists, not snoc. (Then half the content in those slides is useless for this exercise.) So 3b is teaching you structural inversion via recursion (which is the useful half of the slides).
violating the defined data types
Variable t in the code you give is local to function trace, so it seems difficult to access. But its definition
t = trace com s
is not:
We know trace :: Command -> State -> [State]
We can see in the equation for t that trace is applied to two arguments.
So the type of t must be the type of the result of trace, that is [State].
Are you not sure what is the type of the arguments to trace in the equation for t? In particular com unpacked from the Command argument to trace at top level.
Then we need to understand the type for :#:. We have for Question 3
data Command =
Nil
| Command :#: Move
That makes (:#:) an infix operator (which is why I've put it in parens).
Then we can ask GHCi for its type, to make sure.
Use the :type command, make sure to put parens.
For contrast, also ask for the :type of the usual Haskell List constructor (:) -- see the left-right inversion?
The term to the left of (:#:) is of type Command.
Then variable com in the equation for t must be type Command; and that fits what the call to trace is expecting.
How would one debug this (obviously) flawed program using GHC's profiling tools? The program enters an infinite recursion within the second clause of frobnicate.
-- Foo.hs
frobnicate :: Show a => Maybe a -> String
frobnicate Nothing = ""
frobnicate x = case frobnicate x of
"" -> "X"
_ -> show x
main :: IO ()
main = print (frobnicate (Just "" :: Maybe String))
The example might look contrived, but it's actually stripped down version of a real bug I encountered today.
In an imperative language one the mistake would be obvious as the stack trace would say something like frobnicate -> frobnicate -> frobnicate -> .... But how would one discover this in Haskell? How would one narrow down the blame to this one particular function?
I tried something akin to the following:
ghc -fforce-recomp -rtsopts -prof -fprof-auto Foo.hs
./Foo +RTS -M250M -i0.001 -h
hp2ps -c Foo.hp
where the -M250M flag is added to ensure it doesn't kill the machine, -i0.001 increases the profiling frequency in an attempt to catch the overflow in action (which happens very fast).
This produces this rather unhelpful plot:
There is no obvious overflow in this plot. The y-axis doesn't go past even a single megabyte! What am I doing wrong here?
I want to add Haskell to my toolbox so I'm working my way through Real World Haskell.
In the chapter in Input and Output, in the section on hGetContents, I came across this example:
import System.IO
import Data.Char(toUpper)
main :: IO ()
main = do
inh <- openFile "input.txt" ReadMode
outh <- openFile "output.txt" WriteMode
inpStr <- hGetContents inh
let result = processData inpStr
hPutStr outh result
hClose inh
hClose outh
processData :: String -> String
processData = map toUpper
Following this code sample, the authors go on to say:
Notice that hGetContents handled all of the reading for us. Also, take a look at processData. It's a pure function since it has no side effects and always returns the same result each time it is called. It has no need to know—and no way to tell—that its input is being read lazily from a file in this case. It can work perfectly well with a 20-character literal or a 500GB data dump on disk. (N.B. Emphasis is mine)
My question is: how does hGetContents or its resultant values achieve this memory efficiency without – in this example – processData "being able to tell", and still maintain all benefits that accrue to pure code (i.e. processData), specifically memoization?
<- hGetContents inh returns a string so inpStr is bound to a value of type String, which is exactly the type that processData accepts. But if I understand the authors of Real World Haskell correctly, then this string isn't quite like other strings, in that it's not fully loaded into memory (or fully evaluated, if such a things as not-fully-evaluated strings exists...) by the time of the call to processData.
Therefore, another way to ask my question is: if inpStr is not fully evaluated or loaded into memory at the time of the call to processData, then how can it be used to lookup if a memoized call to processData exists, without first fully evaluating inpStr?
Are there instances of type String that each behave differently but cannot be told apart at this level of abstraction?
The String returned by hGetContents is no different from any other Haskell string. In general, Haskell data is not fully evaluated unless the programmer has taken extra steps to ensure that it is (e.g. seq, deepseq, bang patterns).
Strings are defined as (essentially)
data List a = Nil | Cons a (List a) -- Nil === [], Cons === :
type String = List Char
This means that a string is either empty, or a single character (the head) and another string (the tail). Due to laziness, the tail may not exist in memory, and may even be infinite. Upon processing a String, a Haskell program will typically check if it's Nil or Cons, then branch and proceed as necessary. If the function doesn't need to evaluate the tail, it won't. This function, for example, only needs to check the initial constructor:
safeHead :: String -> Maybe Char
safeHead [] = Nothing
safeHead (x:_) = Just x
This is a perfectly legitimate string
allA's = repeat 'a' :: String
that is infinite. You can manipulate this string sensibly, however if you try to print all of it, or calculate the length, or any sort of unbounded traversal your program won't terminate. But you can use functions like safeHead without any problem whatsoever, and even consume some finite initial substring.
Your intuition that something strange is happening is correct, however. hGetContents is implemented using the special function unsafeInterleaveIO, which is essentially a compiler hook into IO behavior. The less said about this, the better.
You're correct that it would be difficult to check if a memoized call to a function exists without having the argument fully evaluated. However, most compilers don't perform this optimization. The problem is that it's very difficult for a compiler to determine when it's worthwhile to memoize calls, and very easy to consume all of your memory by doing so. Fortunately there are several memoizing libraries you can use to add memoization when appropriate.