How to load a script to ghci? - haskell

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

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.

How to tap into hpc information during execution

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.

Haskell functions in GHCi

I am completely new to Haskell. I have been trying to learn how to write functions, lets say to add two integer numbers. I am currently using GHCi to code Haskell. I tried learning from http://www.haskell.org/tutorial/functions.html, however this does not work, I get a not in scope error. I greatly appreciate any help with this. Am I supposed to not use GHCi to code haskell in order to create functions? GHCi, seems to work okay so far, for everything other than functions.
Many thanks in advance.
You have to use let to declare functions in GHCI
ghci>let add x y = x + y
ghci>add 3 3
6
In general though I would advice you to open up a text editor and write your functions in there, save as .hs and open it with :l in ghci
Like this ( from RWH)
-- file: ch03/add.hs
add a b = a + b
Then:
ghci> :l add.hs
[1 of 1] Compiling Main ( add.hs, interpreted )
Ok, modules loaded: Main.
ghci> add 1 2
3

Functions in Haskell

I'm new to functional programming. I have a basic question.
I'm using the Hugs interpreter,
I would like to write a function in Haskell; I went though several tutorials, but I'm not getting it.
fact :: Int -> Int
fact n = if n == 0 then
1
else
n * fact (n-1)
This gives me a syntax error :-S
ERROR - Syntax error in input (unexpected `=')
I assume you type this right into the interactive prompt. Sadly, these are relatively primitive in Haskell - complex definitions, such as fact, can't be entered at the prompt, at least not in the same way you'd normally write them.
You need to put function definitions etc. into modules, then load those via (e.g.) :load fact.hs. There are resources for Hugs specifically that provide more information on this and other topic (I used http://cvs.haskell.org/Hugs/pages/hugsman/index.html to check my assumptions).
Also note that indentation matters, so the code won't work the way you posted it here even when in a module. Those tutorials will have correct versions. If not, they're useless and you should forget them.
The syntax is incorrect. In Haskell, whitespace matters, much like it does in Python. More specifically, if you have text that starts on the first column of a line, the interpreter will think it's a top-level declaration. The correct syntax would be (for example):
fact :: Int -> Int
fact n = if n == 0
then 1
else n * fact (n-1)
You could also put the if in one line if you'd like to. So if you're using an interactive prompt you could do:
λ> let fact n = if n == 0 then 1 else n * fact (n-1)
Notice that you'll need to use let in order to define functions on the prompt (at least this is how it's done in GHCi, I'm not sure about Hugs). You'll be better off putting them in a separate file and then loading that in the interpreter. But anyway, a much nicer solution would use pattern-matching in my opinion anyway:
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)
Here, the interpreter would pattern-match the first argument of the function against the possible cases listed. So if the first argument is null, the result if 1, otherwise apply the function recursively.
Create a file named, for example, fact.hs
-- copying cedric's nicely formatted code
fact :: Int -> Int
fact n = if n == 0
then 1
else n * fact (n-1)
That's all that really needs to be there. When you want to make real modules, you should do some extra stuff.
Now, open up ghci from the same folder. At the ghci prompt, use the :l command to load the "module"
Prelude> :l fact.hs
[1 of 1] Compiling Main ( fact.hs, interpreted )
Ok, modules loaded: Main.
*Main> fact 3
6
*Main> fact 10
3628800
I assume it's a very similar process with Hugs. I think hugs requires the file name to be capitalized. ghci simply creates a "Main" module and puts your code in it; that's why the prompt changes from Prelude> to *Main>
When I work on small Haskell functions, I usually keep two terminals open: one for vim and one for ghci. When I change the file in vim (and save it), I just use :r in ghci to reload the new definitions.
*Main> :r
Ok, modules loaded: Main.
It should be mentioned that the most elegant way to write this function is:
fac n = product [1..n]
See http://www.willamette.edu/~fruehr/haskell/evolution.html for details.

Resources