Making "trace" optimise away like "assert"? - debugging

GHC rewrites asserts when optimising as just id. Or alternatively, it's behaviour can be changed with a compiler flag. However, I noticed the same doesn't happen with trace. Is there a version of trace which just ends up as id if a flag isn't or is set?
More generally speaking, is there a way to alter the behaviour of a function based on the compiler flags used to compile the calling module (not the flags used to compile itself). Much like assert does. Or is this GHC magic that can only happen with assert?

Warning: I haven't tried this ...
You can replace the Debug.Trace module completely with compiler flags. Make another module with trivial implementations of the functions in Debug.Trace:
module NoTrace (trace) where:
trace :: String -> a -> a
{-# INLINE trace #-}
trace _message = id
...
Put this module in another package named no-trace.
Hide the Debug.Trace module in the arguments to ghc by including every module from the base package except Debug.Trace. Replace Debug.Trace with NoTrace from the no-trace package.
ghc -package="base (Control, Control.Applicative, ..., Data.Word, Foreign, ...)" \
-package="no-trace (NoTrace as Debug.Trace)" \
...
This came from the crazy idea of using the compiler flag that changes the prelude to replace the prelude with one that had rewrite rules to remove traces, but those rewrite rules would taint anything that imported a module compiled with them, even if a downstream importer still wanted to use traces. When looking up how to replace the prelude I found that ghc can replace any module instead.

No, at least not based on assert. The magic for assert works the other direction and replaces the identity function with an assertion.
Here's assert from base 4.9:
-- Assertion function. This simply ignores its boolean argument.
-- The compiler may rewrite it to #('assertError' line)#.
-- | If the first argument evaluates to 'True', then the result is the
-- second argument. Otherwise an 'AssertionFailed' exception is raised,
-- containing a 'String' with the source file and line number of the
-- call to 'assert'.
--
-- Assertions can normally be turned on or off with a compiler flag
-- (for GHC, assertions are normally on unless optimisation is turned on
-- with #-O# or the #-fignore-asserts#
-- option is given). When assertions are turned off, the first
-- argument to 'assert' is ignored, and the second argument is
-- returned as the result.
-- SLPJ: in 5.04 etc 'assert' is in GHC.Prim,
-- but from Template Haskell onwards it's simply
-- defined here in Base.lhs
assert :: Bool -> a -> a
assert _pred r = r

OK, back at my computer and finally remembered I wanted to demonstrate this. Here goes:
import Control.Exception
import Debug.Trace
import Control.Monad
traceDebug :: String -> a -> a
traceDebug msg = assert (trace msg True)
main :: IO ()
main = replicateM_ 2 $ do
print $ traceDebug "here1" ()
print $ traceDebug "here2" ()
print $ traceDebug "here3" ()
When compiled without optimizations, the output is:
here1
()
here2
()
here3
()
()
()
()
With optimizations:
()
()
()
()
()
()
So I think this addresses the request, with the standard caveat around trace that once the thunk has been evaluated, it won't be evaluated a second time (which is why the messages only happen the first time through the do-block).

Related

lldb complains about variable named "this"

I'm using Xcode/lldb to debug some C code. But I get this error
(lldb) p (int)g_list_position(start, next)
(int) $0 = 1
(lldb) p (int)g_list_position(start, this)
error: expected unqualified-id
error: invalid use of 'this' outside of a non-static member function
So apparently lldb things "this" is a reference to a class, in spite of it being a perfectly valid var in C (and its value is 0, as it should be). Is there some way to escape this name in lldb?
No, the expression evaluator in lldb wraps your expression (at at a source level) with some C++ to pass the arguments in. The only suggestion I can think of is to get the address in the this pointer and put that in the expression explicitly. It's a goal of the expression evaluation that you can copy a line of source in your program and execute it as an expression in lldb .. but this is a corner case where that does not work - variables in C that are reserved words in C++.

Why does ghci behave differently to runHaskell?

My goal is to pipe some steps for ghci to run from a bash script and then exit cleanly. The commentary online says to use runhaskell for this.
This is the command I'm trying to run:
ghci> import System.Random
ghci> random (mkStdGen 100) :: (Int, StdGen)
With expected result similar to:
(-3633736515773289454,693699796 2103410263)
When I drop this into a file randomtest.hs and execute it with runhaskell I get the following error:.
randomtest.hs:3:1: error:
Invalid type signature: random (mkStdGen 100) :: ...
Should be of form <variable> :: <type>
I need a hint to go in the right direction.
My question is: Why does ghci behave differently to runHaskell?
ghci is a REPL (Read, Eval, Print Loop). However, runhaskell is nearly the same as compiling a program into an executable, and then running it. GHCI lets us run individual functions and arbitrary expressions, wheras runhaskell just calls the main function and interprets the file, instead of compiling it, and running that.
As #AJFarmar points out, GHCI is best used to debug and test a program you're building, whilst runhaskell is a nice way to run a whole program without having to compile.
So, to fix your issue, we just need to give the program a main function. ghci calls print on the result of every expression which is typed into the interpreter and not bound to a variable.
So, our main function can just be:
main = print (random (mkStdGen 100) :: (Int, StdGen))
We still need to import System.Random, so the whole file becomes:
import System.Random
main = print (random (mkStdGen 100) :: (Int, StdGen))
Then, we can run as expected:
[~]λ runhaskell randomtest.hs
(-3633736515773289454,693699796 2103410263)
If we want to multiple commands from runhaskell we can just add more to a do block in main:
import System.Random
main = do
print (random (mkStdGen 100) :: (Int, StdGen))
let x = 5 * 5
print x
putStrLn "Hello world!"

Why does CMake syntax have redundant parentheses everywhere?

CMake's ifs go like this:
if (condition)
...
else if (...)
...
else (...)
...
endif (...)
With else if (...) the (...) tests for a separate condition.
Why else (...) and not just else? Why endif (...) and not endif?
Cmake's functions go like this:
function(funcname ...)
...
endfunction(funcname ...)
Why endfunction(funcname ...) and not simply endfunction?
I can omit the contents of the redundant parenthesis where they appear, like so: endif (). What's the purpose of this construct?
I believe the initial intention was that, by repeating at each clause (for example, else statement) the initial expression (for example, the one at the if statement) it would make more clear which statement was actually closed, and the parser could verify and warn nothing wrong was going on.
However, it turned out that you would have expression like:
if (VARIABLE matches "something")
[...] #This is executed when above condition is true
else (VARIABLE matches "something") #Looks very much like an elseif...
[...] #This is executed when above condition is false!
endif (VARIABLE matches "something")
Which turned out to be confusing. I am speaking about my every day experience, e.g. I write something and somebody else come to ask me "What does this does?"
So, now CMake allows also to put empty parenthesis, the above can be rewritten as:
if (VARIABLE matches "something")
[...] #This is executed when above condition is true
else ()
[...] #This is executed when above condition is false
endif ()
Which can be considered clearer. The grammar above can still be used.
To completely answer to your question, the parenthesis stay also with empty arguments because conceptually else and endif in CMake are macros like if, and therefore they are invoked with this grammar, a little bit (but not at all exactly) as functions.
Basically the same explanation is available in CMake FAQs: Isn't the "Expression" in the "ELSE (Expression)" confusing?.
To add a little bit of history, in CMake 2.4 repeating the expression was obligatory, and still in CMake 2.6, at least according to the documentation. The documentation was ambiguous on else, but adamant on endif:
Note that the same expression must be given to if, and endif.
The first try to remove this constraint was introduced already with CMake 2.4.3 (year 2006), where it was possible to deactivate it by writing:
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
This constraint became fully optional with CMake 2.8
Note that the expression in the else and endif clause is optional.

stepping through a function line by line

This user guide:
http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-debugger.html
advertises:
Execution can be single-stepped: the evaluator will suspend execution
approximately after every reduction, allowing local variables to be
inspected. This is equivalent to setting a breakpoint at every point
in the program.
Yet, I can find nothing in the document that tells me how to do that. Under the heading:
2.5.2. Single-stepping
It describes how to step from breakpoint to breakpoint. But I don't want to have to set a breakpoint on every line. Was the advertisement false or is there a way to step through a program line by line?
Thanks.
After having set and reached a breakpoint, you can call :step from the debugger.
There are other single-step possibilities. Typing :help once at a breakpoint would tell you more about what you can do.
Okay, I figured it out:
ghci> :step function_name arg1 arg2
...
...
ghci> :step
...
...
ghci> :step
If you forget the function arguments, then you will get the cryptic error message:
<interactive>:138:1:
No instance for (Show (String -> Double))
arising from a use of `print'
Possible fix:
add an instance declaration for (Show (String -> Double))
In a stmt of an interactive GHCi command: print it
...which might lead you to tear your hair out. And if you want to skip to the end:
ghci> :continue

Inputting Data with Haskell

Back Story: In an attempt to better understand Haskell and functional programming, I've given myself a few assignments. My first assignment is to make a program that can look through a data set (a set of numbers, words in a blog, etc), search for patterns or repetitions, group them, and report them.
Sounds easy enough. :)
Question: I'd like for the program to start by creating a list variable from the data in a text file. I'm familiar with the readFile function, but I was wondering if there was a more elegant way to input data.
For example, I'd like to allow the user to type something like this in the command line to load the program and the data set.
./haskellprogram textfile.txt
Is there a function that will allow this?
import System.Environment
main :: IO ()
main = do
args <- getArgs
-- args is a list of arguments
if null args
then putStrLn "usage: ./haskellprogram textfile.txt"
else do contents <- readFile $ head args
putStrLn $ doSomething contents
doSomething :: String -> String
doSomething = reverse
That should be enough to get you started. Now replace reverse with something more valuable :)
Speaking of parsing some input data, you might consider breaking your data into lines or words using respective functions from Prelude.
You're looking for getArgs function.
Subtle Array, I can never resist mentioning my favorite when I was first learning Haskell, interact:
module Main where
main = interact doSomething
doSomething :: String -> String
doSomething xs = reverse xs
you then use it as cat textfile.txt | ./haskellprogram | grep otto or whatever. There is also a variant in Data.Text which you might get to know, and a few others in other string-ish libraries.
Playing with the relatively new ReadArgs package:
{-# LANGUAGE ScopedTypeVariables #-}
import ReadArgs (readArgs)
main = do
(fname :: String, foo :: Int) <- readArgs
putStrLn fname
Testing...
$ runhaskell args.hs blahblah 3
blahblah
One irritation with readArgs is that it doesn't work if you have only a single argument. Hmmm...
Once you have the desired file name as a String, you can use readFile as usual.

Resources