Adapted for 4700 from The Hugs
98 User Manual
(Eclipse has support for Haskell, but because I suspect
you all won’t take the time to get Eclipse to work, I’ll explain
the interface all of you can use.)
Download Hugs
Go to the download site and select the Hugs for Windows named hugs98-Nov2003-2.msi. (It is also available for Linux.) Follow the prompts.
To run from the start menu, select Hugs98 and then Hugs (Hugs mode).
[You can also start the interpreter by double clicking on a .hs or .lhs file.]
Starting the interpreter produces a
startup banner something like the following
__ __ __ __ ____ ___ _________________________________________
|| || || || || || ||__ Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__|| __|| Copyright (c) 1994-2003
||---|| ___|| World Wide Web: http://haskell.org/hugs
|| || Report bugs to: hugs-bugs@haskell.org
|| || Version: Nov 2003
_________________________________________
Hugs mode: Restart with command line option +98 to enable Haskell
98 mode
Type :? for help
Prelude>
The file /Hugs/lib/Prelude.hs mentioned here contains standard
definitions that are loaded into Hugs each time that the interpreter is
started.
In essence, using Hugs is just like using a calculator; the
interpreter simply evaluates each expression that is entered, printing the
results as it goes.
Prelude> (2+3)*8
40
Prelude> sum [1..10]
55
Prelude>
The Prelude> characters at the beginning of the first, third and fifth lines form the Hugs prompt. This indicates that the system is ready to accept input from the user, and that it will use definitions from the Prelude module to evaluate each expression that is entered; The Hugs prelude is a special module that contains definitions for the built-in operations of Haskell, such as +, *, and sum. In response to the first prompt, the user entered the expression (2+3)*8, which was evaluated to produce the result 40. In response to the second prompt, the user typed the expression sum [1..10]. The notation [1..10] represents the list of integers between 1 and 10 inclusive, and sum is a prelude function that calculates the sum of a list of numbers.
So the result obtained by Hugs is:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55.
In fact, we could have typed this sum directly into Hugs:
Prelude> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
55
Prelude>
Unlike many calculators, however, Hugs is not limited to working with
numbers; expressions can involve many different types of value, including
numbers, booleans, characters, strings, lists,
functions, and user-defined datatypes.
Some of these are illustrated in the following example:
Prelude> (not True) || False
False
Prelude> reverse "Hugs is cool"
"looc si sguH"
Prelude> filter even [1..10]
[2, 4, 6, 8, 10]
Hugs even allows whole programs to be used as values in calculations. For
example, putStr "hello, "
is a simple program that outputs the string "hello, ".
Combining this with a similar program to print the string "world", gives:
Prelude> putStr "hello, " >> putStr "world"
hello, world
Prelude>
Just as there are standard operations for dealing with numbers, so there
are standard operations for dealing with programs. For example, the >> operator used here constructs a
new program from the programs supplied as its operands, running one after the
other. Normally, Hugs just prints the value of each expression entered. But, as
this example shows, if the expression evaluates to a program, then Hugs will
run the program. Hugs distinguishes programs from other expressions by looking
at the type of the expression entered. For example, the expression putStr "world" has type IO (), which identifies it as a
program to be executed rather than a value to be printed.
Each line that you enter in response to the Hugs prompt is treated as a command to the interpreter. For example, when you enter an expression into Hugs, it is treated as a command to evaluate that expression, and to display the result. There are two commands that are particularly worth remembering:
Like most other commands in Hugs, these commands both start with a colon, :.
Note that the interrupt key (control-C or control-Break on most systems) can be used to abandon the process of compiling files or evaluating expressions. When the interrupt is detected, Hugs prints {Interrupted!} and returns to the prompt so that further commands can be entered.
Functions like sum, >> and take, used in the examples above, are all defined in the Hugs prelude; you can actually do quite a lot using just the types and operations provided by the prelude. But, in general, you will also want to define new types and operations, storing them in modules that can be loaded and used by Hugs. A module is simply a collection of definitions stored in a file.
You can generate a file from within the Hugs environment. Just type :edit filename.hs from the hugs prompt. An editor will be opened for you and Hugs even remembers where it puts the file (so a full pathname is not needed). For this example, create a program called fact.hs. Enter the following lines in this file:
module Fact where
fact :: Integer -> Integer
fact n = product [1..n]
The
meaning of these lines is explained below:
module Fact where //module is a keyword, Fact is the name you want the system
to use in referring
to this file. The module name must be capitalized.
where is also required part of the format. If you
leave off the module, it defaults to calling the
module
fact :: Integer -> Integer
// indicates r that the module fact takes one Integer input and
produces a single Integer output. The notation is similar to
the mathematics notation for indicating domain
and range.
fact n = product [1..n]
// indicates the name of the parameter (n) and how to compute the
result using built-in functions
By convention, Hugs modules are stored in files ending with the characters .hs. The file name should match the name of the module it contains.
Save the file and exit the editor. From within hugs, type :load fact.hs
Other choices for editing/loading
a file:
1. You can use a provided file as a starting point. You
will need to load it using a complete path name such as
:load C:\me\Class\cs4700\Haskell\fact.hs.
Lucky for you, the system
remembers the path name during the session, so you can re-edit the file without
typing in the whole name every time.
Note, too, that you can get to a
previously entered line in the interpreter by typing up arrow.
2. You can use notepad (or a similar editor) to create the file outside of the Hugs environment, and then load it (as described above).
The prompt is now Fact and
evaluation will take place within this new module. We can use the fact function that we have defined:
Fact> fact 6
720
Fact> fact 6 + fact 7
5760
Fact> fact 7 `div` fact 6
7
Fact>
As another example, the standard formula for the number of different ways of choosing r objects from a collection of n objects is n!/(r!(n-r)!). A simple and direct (but otherwise not particularly good) definition for this function in Hugs can be added to fact.hs. Open the editor by typing :e and then type :
comb :: Integer
->Integer ->Integer
comb n r = fact n `div` (fact r * fact (n-r))
Notice the way you specify two
parameters.
Another way to use this function is to include its definition as part of an
expression entered in directly to Hugs:
Fact> combin 5 2 where combin n r = fact n `div` (fact r * fact (n-r))
10
Fact>
The definition of combin
here is local to this expression. If we want to use the function several times, then it must be added to the
file Fact.hs. You can edit the previous file you
loaded by typing :edit. This brings up a notepad window for you
to edit the file. The interpreter
is suspended until you save the file and exit notepad. You can reload the
previously loaded file by simply typing :reload or
simply :r. Once this has been done, then we can use
the comb function like any other
built-in operator:
Fact> :reload
Fact> comb 5 2
10
Fact>
Identifiers must begin with a letter (small or
capital) and be followed by an optional sequence of letters, digits,
underscores and single quotes.
Variables must be lower case.
Capital letters are used to begin type names (such as Int), constructors (such as True or False), module names
and the name of type classes.
Exercise 1: Create a function increment which
takes one argument and adds 1 to it.
Exercise 2: Create a function area which takes
two arguments representing length and width of a rectangle and returns the
area.