Abstract :: We present a “Hello World” program for Haskell, followed by some technical facts about the Haskell language. Essentially​, we briefly summarise some parts of the first chapter of Real World Haskell.


a first program

Make a file named myprog.hs with contents

main = putStrLn "Hello World"

Now, runghc myprog.hs in a command line to execute this program.

runghc is a program for running Haskell programs as scripts, without needing to compile them first. In contrast, ghci is an interactive interpreter and debugger.

Try Haskell online in your browser at this link 😉

The rest of this page consists of tidbits on numbers, lists, operators and interactive​ debugging of Haskell programs.

the wonders of ghci

ghci is a Haskell interpreter and run from a console by running ghci myprog.lhs. Entering :? at the ghci prompt yields a collection of helpful commands to run. For example, :module + Data.Ratio loads the Data.Ratio module into the current session.

Other tidbits

  • :t identifier to obtain type information for identifier; use :i for all information.
  • At the ghci prompt, the variable it refers to the previously evaluated expression. This makes it easier to work with previous expressions.
  • :r to reload your file after you’ve made some changes

I personally use ghci as an overglorified calculator XD

operators in Haskell

Operator symbols appear infix as in most other languages, eg 3 + 4, but can also appear in prefix form by parenthesising them: (+) 3 4.

Haskell uses nearly the same names for the common arithmetical and logical operators with notable exceptions being ^ and ** for exponentiation, /= for non-equality, and not for Boolean negation. The ^ has an integer as the exponent but ** allows the exponent to be fractional.

At a ghci prompt, we can run :info (op) to see the precedence level of op, with 9 being the highest level and 1 the lowest. For example, infixl 6 means that the operator has level 6 precedence and is by default left-associative; the alternatives are infixr, infix for infix with default right-associative parsing, and for infix with no specified parsing order. The associativity determines whether an expression containing multiple uses of an operator is evaluated from left to right or right to left; eg how do you normally parse repeated fractions 6/2/3? Run :info (/) to find out what Haskell does! 😛

negation and parenthesisation

The usual notion of subtraction and negation is to use the same overloaded symbol - and Haskell accepts this and so the former is a binary operation whereas the latter is unary. In particular, if we wish to negate a number enclosed in some expression f, we must write f (-3) rather than f -3 since the latter is ambiguous and may be parsed as the subtraction of f with 3.

Note that function calls in Haskell do not require superfluous enclosing parenthesis as in other languages, unless there would be ambiguity otherwise. Function application has the highest binding: It is done first.

Moreover, Haskell allows us to define our own operators! More on this later. Hence, spacing about operators is important! 😮

In doubt, parenthesis your expressions.

lists, the bread and butter of Haskell programmers

A list is surrounded by square brackets and its elements are separted by commas as in [1,2,4,8,16,32,64] for the list of a few powers of 2. The empty list is denoted [].

enumerated lists

If the elements belong to an enumerable type, such as the numbers or characters, then we can write [x..y] to obtain the list starting at x and enumerating upto y. For numbers, we can specify the increment for each step by including the first two elements of the resulting list: [x,y..z] produces the list [x, x+d, x+2*d, ..., x+n*d] where d = y – x and x + n*dz. For example, [1.0, 0.75..0] == [1.0, 0.75, 0.50, 0.25, 0]. Moreover, [x..] produces the infinite list enumerated from x onwards —infinite lists are very useful and implemented very simply and efficiently! Press Ctrl C to stop a ghci computation, such as that of evaluating [1..]! Unless giving a step size, there are dangers with using enumerations with fractional endpoints.

Lists can be catenated together to form longer lists using ++ and we can construct a new list given an element x and a list xs by the operation : as in x:xs.

Strings —formed by enclosing text in double quotes— are synonyms for lists of characters —which are formed by enclosing a symbol by single quotes. Eg “Hello” == [‘H’, ‘e’, ‘l’, ‘l’, ‘o’]. As such usual list operations work on Strings.

be rational; we’re nearly done

A rational number is a number expressible as a fraction of two integer numbers; for example, a third is rational since it equals 1/3 whereas the square root of two is not rational and this drove a few fanatical mathematicians too keep it secret… o_O

Anyhow, Haskell treats rational numbers exactly in this form and one can construct them via the operator %: the fraction with integer numerator n and integer denominator d is named n % d. This way we can do very “precise” arithmetic since we do not express the rationals in floating-point form. Eg which is better 1 % 3 or 0.333, no matter how many trailing 3’s the latter will always be worse than the former; incidentally, three times the former is 1 but three times the latter is close to 1, but is not 1! :mrgreen:

Advertisements