Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Haskell Basics

The whole lesson is here to read. Create a free account to run it in a live lab.

Container lab12 min read9 commands

Can a program tell you it is wrong before it runs?

A spreadsheet that adds a name to a number gives a strange answer, and you find out later. Haskell asks you to say what kind of thing each function takes and gives back, and checks that before anything runs. Then a whole class of mistakes cannot happen.

By the end of this lesson

Note

I can read and run a Haskell function and say what its type tells me.

Key words

  • Function: something that takes a value and gives a value back.
  • Type: the kind of value, such as Int for a whole number or String for text.
  • Type signature: the line that gives a function its type, such as square :: Int -> Int.
  • List: several values of one type in order, written [1, 2, 3].
  • Fold: a way to combine every item of a list into one value.

Starter: what you already know

Note

Answer in your head. 1. In maths, if f(x) = x * x, what is f(5)? 2. Is 7 the same kind of thing as "seven"? 3. What is the sum of the list 1, 2, 3? Answers: 25; no, one is a number and the other is text; 6.

Before you start

Note

Press Start the lab on the bar at the top of this lesson and wait until it says it is running. There is one container, haskell. Nothing opens in a browser, so use the terminal, where docker exec haskell runs one command inside it. The compiler takes a couple of seconds to start each time. Everything printed is in English, whatever language this page is in. Each Run button below types its command into your lab's terminal, one after another in the same session. To watch them, or to type your own, press Open terminal on the bar.

A function has a type signature

This prints the first file. The line square :: Int -> Int is a type signature. Read it as "square takes an Int and gives back an Int". The next line says how: square n = n * n. A function has no side effects here: give it the same value and you get the same answer. -- starts a comment.

Command
docker exec haskell cat Basics.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Run a file, or ask about one function

runghc runs the file. Its main prints three lines: Hello, Haskell!, then 49, then (True,False). The ghc -e options work out one expression with the file loaded: the first asks for the type of square and prints square :: Int -> Int, and the second calls it and prints 144.

Command
docker exec haskell runghc Basics.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Command
docker exec haskell ghc -e ":type square" Basics.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Command
docker exec haskell ghc -e "square 12" Basics.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Check

Tip

What does isEven :: Int -> Bool tell you before you read the code? Answer: it takes a whole number and gives back True or False.

A list is worked on with functions

map applies a function to every item and filter keeps the items that pass a test. The first command squares 1 to 5 with square and adds them up with sum: it prints 55. The second keeps the even numbers from 1 to 10 and prints [2,4,6,8,10]. Neither changes the original list: each gives a new value.

Command
docker exec haskell ghc -e "sum (map square [1 .. 5])" Basics.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Command
docker exec haskell ghc -e "filter even [1 .. 10]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A function can call itself, and a fold does it for you

mySum in Fold.hs adds a list by adding the first item to the sum of the rest, and stopping at the empty list. This prints 6. The second command does the same job with the built-in foldr, which folds a list into one value: it prints 5050, the sum of 1 to 100.

Command
docker exec haskell ghc -e "mySum [1, 2, 3]" Fold.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Command
docker exec haskell ghc -e "foldr (+) 0 [1 .. 100]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The compiler checks the types

This gives square some text instead of a number. Nothing runs. The compiler prints an error that starts with <interactive> and says it could not match the type [Char], which is text, with Int. Read the error from the top: it names the part of your expression that is wrong. The code in brackets and the layout can differ between versions.

Command
docker exec haskell ghc -e "square \"two\"" Basics.hs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think a type signature is only a comment for the reader. It is not. The compiler checks every one, and if the code does not match, nothing runs at all. Write the signature first when you can: it says what you meant, and the compiler tells you when the code says something else.

Exit check

Tip

Answer without looking back. 1. What does Int -> Bool mean? 2. What does filter even [1 .. 10] give? 3. When does the compiler find a type error: before the program runs or after? 4. What does a fold do to a list? Answers: takes a whole number and gives True or False; [2,4,6,8,10]; before, so nothing runs; it combines every item into one value.

For teachers

Tip

This lesson is a small example of a lesson worked in a lab: the steps and the Run buttons are the lesson, and the lab is each student's own copy. The lab is one container with the GHC compiler and four small files, and nothing here marks itself: the student hands in the expressions they tried and what each printed, a function of their own with its type and a call that shows it, and a sentence on what a type signature tells the reader. Key learning points: 1. A function takes a value and gives one back. 2. A type signature says what a function takes and gives. 3. Lists are worked on with functions such as map and filter. 4. A function can call itself, and a fold does the same job. 5. The compiler checks types before anything runs. Common mistake: treating a signature as a comment. Equipment: the lab and its terminal. Tip: ask students to write the type of a function before they write its body. Every answer is exact and the same each time; the first command after a start takes a couple of seconds. Names and messages are in English, whatever language the page is in. Copy it into your own module and change it, or build one from scratch with the Lab menu in the lesson builder.

About this lab and its source: Haskell lab: functional programming with functions and types, in the browser

Teaching a class? Set these lessons for your students with marking and a lab for every student.