How to tap into hpc information during execution - haskell

Consider the following use case:
I have a QuickCheck test suite consisting of two test cases prop_testCase1 and prop_testCase2. Using hpc I can observe the code coverage of my test suite.
However, I'd like to get separate results for the coverage of prop_testCase1 and prop_testCase2 (to then further process the results).
One way out could be to run the executable several times explicitly specifying the test case as a command line argument and to process the generated tix file after each run.
Yet, I would prefer to hide away this logic in a library. Also in reality I would like to run significantly more than just two test cases. Thus explicitly re-executing the binary for each test case seems rather inconvenient.
At the same time I'd imagine that hpc keeps the coverage data in some kind of intermediate data structure during the program execution.
Question: Is there a way to recognize that the program has been compiled with hpc symbols and to somehow access the data hpc generates at runtime?

I think I found a way to achieve the desired effect.
The required functions are provided by the Trace.Hpc.Reflect module.
Unfortunately the documentation is somewhat lacking.
Nevertheless, here is a minimal example that seems to work:
import Trace.Hpc.Reflect
main :: IO ()
main = do
print (show $ f 5)
tix <- examineTix
print (show tix)
print (show $ f 6)
print (show $ f 7)
tix <- examineTix
print (show tix)
return ()
f x = x*2
Compile and run this as follows:
$ ghc -fhpc Main
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking Main ...
$ ./Main
"10"
"Tix [TixModule \"Main\" 3889152622 31 [1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1]]"
"12"
"14"
"Tix [TixModule \"Main\" 3889152622 31 [3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, in1,1,1,1,0,0,0,0,0,1,1]]"
So using this you can tap into the coverage data provided by hpc while your program is executing.
If the executable is compiled without hpc support the program still works but the Tix object returned by examineTix contains the empty list.

Related

Haskell: Parse error: module header, import declaration or top-level declaration expected

I am saving some commands in a Haskell script in a .hs file while working thru a Haskell textbook. Here's a small example.
fst (1,2)
snd (1,2)
When I run these commands from the prelude in GHCi, they work fine. When I try to compile the .hs file with these two lines, I get the following:
ch4_test.hs:2:1: error:
Parse error: module header, import declaration
or top-level declaration expected.
|
2 | fst (1,2)
| ^^^^^^^^^
Failed, no modules loaded.
I've googled this error and can't find any explanation what I'm doing wrong.
From a newbie to future newbies: The interactive environment ghci would lead you to believe that you can punch some expressions into an .hs file and run the thing (in a similar fashion to languages like swift and ruby). This is not the case.
Haskell needs an entrypoint called main. Quoting:
Here is a simple program to read and then print a character:
main :: IO ()
main = do c <- getChar
putChar c
The use of the name main is important: main is defined to be the entry point of a Haskell program (similar to the main function in C), and must have an IO type, usually IO ()
Source: https://www.haskell.org/tutorial/io.html
You can't just put any expression in a hs file.
As the error message says, you need a declaration here. For example:
main =
print (fst (1,2)) >>
print (snd (1,2))
I am getting this error but the cause appears to be completely different from anything posted here. And the error message is not at all helpful.
Using Cabal version 3.6.2.0 with GHCI 8.10.7 on MacOS High Sierra (10.13)
I'm working from this page: https://www.tutorialspoint.com/haskell/haskell_modules.htm
specifically the "custom modules" section. There you can see the code I copied and pasted.
Besides the tutorial not mentioning I needed to add "other-modules: Custom" to myfirstapp.cabal, and besides the fact that the sample Custom.hs file includes "if x 'rem' 2 == 0" rather than "if x rem 2 == 0", here is the problem:
Indentation matters!
This line (inside the quotes) does NOT work "if x rem 2 == 0".
This line DOES work " if x rem 2 == 0"!
Indenting by one space is the difference between success and failure.
I'm totally new to Haskell. I've programmed extensively in PHP, Javascript, and Applescript, and dabbled in a dozen others, and this is the first time I've seen white space matter. I assume this is commonly known amongst Haskell veterans, but it would certainly be nice if that was included prominently in the documentation.

Why is my Haskell code saying 'variable not in scope: main'?

When I type the following in the interactive shell of Haskell on the repl.it website, it works perfectly.
let squareMe x = x * x
let myFruit = ["banana", "apple", "kiwi", "orange"]
But when I type it into a source file and click 'Run' I get the error:
<interactive>:3:1: error:
• Variable not in scope: main
• Perhaps you meant ‘min’ (imported from Prelude)
I've been trying to understand this error and come up with a solution for a couple of hours now and am no nearer to finding a solution or understanding what the error means.
The Haskell REPL (GHCi) and actual Haskell programs are considerably different.
The reasons for this difference is the goal of the two formats. Firstly, GHCi is a testing area, not a code-running area. However, Haskell source files are meant to run a certain process, which is named main. When you run a source file, the Haskell compiler (usually GHC) looks for the IO action called main, and tries to run it. In this case, there was no main, so it failed.
Secondly, what you typed is not a valid Haskell program, those are declarations that would be fine in GHCi, but not in Haskell source. This would be correct in a source file:
squareMe x = x * x
myFruit = ["banana", "apple", "kiwi", "orange"]
Note the lack of let; Haskell source files don't use it to declare things.
Note that on repl.it, this will still complain that main is missing, but you can then refer to squareMe and myFruit in the REPL without worry. In other words, the error will still appear, but it doesn't matter, because you can use whatever you wrote in the file nonetheless.
If you wanted to suppress the warning, you could write the lines:
main :: IO () -- This says that main is an IO action.
main = return () -- This tells main to do nothing.
There are many things you could have the program do instead of this. Here are a couple of examples:
main = putStrLn "No errors!" Will print No errors! when you run it.
main = print myFruit Will print ["banana", "apple", "kiwi", "orange"] when you run it.
Please note that this answer applies mostly to the site repl.it specifically, though in general this is how Haskell programs are structured.
If you compile a Haskell source there needs to be a main symbol as entry point, just like when compiling e.g. a C program. Also in a compiled file you must skip the lets. E.g.
squareMe x = x * x
main = putStrLn . show $ squareMe 4
If what you’re writing is more like a library or a set of utility routines than a complete program, you can declare it as a module. Then GHC will compile it to an object you can link to other programs, and you can also load it in GHCI. It will not be expected to contain a main routine.
If you save this to a .hs file:
module Example (squareMe) where
squareMe x = x * x -- Exported to other modules.
myFruit = ["banana", "apple", "kiwi", "orange"] -- Not exported.
Compiling this with GHC will give you a .hi file and a .o file, and running it in GHCI will give you this:
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Ok, modules loaded: Example (sx-modulexmpl.o).
Prelude Example> squareMe 2
4
You can also compute an expression that references a library from the command line. ghc -e "squareMe 2" Example.hs prints 4.

GHC: insert compilation date

I thought there would already be a question about this, but I can't find one.
I want my program to print out the date it was compiled on. What's the easiest way to set that up?
I can think of several possibilities, but none of them are what you'd call "easy". Ideally I'd like to be able to just do ghc --make Foo and have Foo print out the compilation date each time I run it.
Various non-easy possibilities that spring to mind:
Learn Template Haskell. Figure out how to use Data.Time to fetch today's date. Find a way how to transform that into a string. (Now my program requires TH in order to work. I also need to convince it to recompile that module every time, otherwise I get the compilation date for that module [which never changes] rather than the whole program.)
Write a shell script that generates a tiny Haskell module containing the system date. (Now I have to use that shell script rather than compile my program directly. Also, shell scripting on Windows leaves much to be desired!)
Sit down and write some Haskell code which generates a tiny Haskell module containing the date. (More portable than previous idea - but still requires extra build steps or the date printed will be incorrect.)
There might be some way to do this through Cabal - but do I really want to package up this little program just to get a date facility?
Does anybody have any simpler suggestions?
Using Template Haskell for this is relatively simple.
You just need to:
Run IO action within Template Haskell monad:
runIO :: IO a -> Exp a
Then create a string literal with:
stringE :: String -> ExpQ
Put a whole expression within a quasiquote.
$( ... )
This program will print time of its compilation:
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Data.Time
main = print $(stringE =<< runIO (show `fmap` Data.Time.getCurrentTime))
You may put the relevant fragment into a module that imports all other modules to make sure it is recompiled.
Or take current revision information from your versioning system. See: TemplateHaskell and IO
The preprocessor helpfully defines __DATE__ and __TIME__ macros (just like in C), so this works:
{-# LANGUAGE CPP #-}
main = putStrLn (__DATE__ ++ " " ++ __TIME__)
This is probably simpler than Michal's suggestion of Template Haskell, but doesn't let you choose the format of the date.

How to load a script to ghci?

I'm just starting learning Haskell, and having a hard time understanding the 'flow' of a Haskell program.
For example in Python, I can write a script, load it to the interpreter and see the results:
def cube(x):
return x*x*x
print cube(1)
print cube(2)
print cube(cube(5))
# etc...
In Haskell I can do this:
cube x = x*x*x
main = print (cube 5)
Load it with runhaskell and it will print 125.
Or I could use ghci and manually type all functions I want to test
But what I want is to use my text editor , write a couple of functions , a few tests , and have Haskell print back some results:
-- Compile this part
cube x = x*x*x
-- evaluate this part:
cube 1
cube 2
cube (cube 3)
--etc..
Is something like this possible?
Very possible!
$ ghci
> :l filename.hs
That will load the file, and then you can use the functions directly.
> :r
That will cause the file to be reloaded after you make an edit. No need to mention the file, it will reload whatever the last one you loaded was. This also will work if you do ghci filename.hs initially instead of :l.
cube x = x*x*x
main = do
print $ cube 1
print $ cube 2
print $ cube (cube 3)
$ ghci cube.hs
...
ghci> main
See the GHCI user guide.
I also highly recommend checking out the QuickCheck library.
You'll be amazed at how awesome testing can be with it.
To load a Haskell source file into GHCi, use the :load command
cf Loading source file in Haskell documentation

Why cannot top level module be set to main in Hint

Why cannot top level module be set to "Main" in Hint (Language.Haskell.Interpreter)?
Allow me to demonstrate:
module Main where
import Language.Haskell.Interpreter
import Control.Monad
main = do
res <- runInterpreter (test "test")
case res of
Left e -> putStrLn (show e)
Right t -> putStrLn (show t)
return ()
test :: String -> Interpreter ()
test mname =
do
loadModules [mname ++ ".hs"]
setTopLevelModules ["Main"]
Will result in:
NotAllowed "These modules are not interpreted:\nMain\n"
As the documentation says, top level modules have to be interpreted, i.e. not compiled.
When loading a module, a compiled version will be used if it's available. The GHCi manual has more detailed information on this.
I'm guessing there's a test.o and test.hi in the same folder from an earlier build. I was able to reproduce the error with these files present. Deleting them solves the problem, as the module will then be interpreted.
You can also force a module to be loaded in interpreted mode by prefixing the module name with an asterisk, e.g. loadModules ["*" ++ mname ++ ".hs"].
It would appear that it compiles the code OK, but then when it goes back to load the current interpreted modules, a problem occurs.
It loads Main with findModule, but, apparently, loads the wrong Main: It's loading the application Main, which indeed was not interpreted, sees that, and dies.
(Though I should add I haven't used Hint so I'm kind of guessing ;)

Resources