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. 

Hugs for beginners

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.

Expressions

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.

Commands

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.

Programs

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 Main.
 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>

Names in Haskell

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.