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 functions and types

After this lesson: I can read a small Haskell function and say what its type means.

60 min lesson8 commandsHaskell lab: functional programming with functions and types, in the browser

What is a function with a type?

Haskell is a functional programming language. A program is built from functions, and every function has a type that says what it takes and what it gives back.

This matters because the type catches many mistakes before the program runs. In this lesson you read small functions that work out prices and learn what each type tells you.

By the end of this lesson

Note

I can read a small Haskell function and say what its type means.

Key words

WordWhat it meansExample
Functionsomething that takes values in and gives a value back
Pure functiona function whose answer depends only on what it is given
Typethe kind of value, such as a whole number or textInt
Type signaturethe line that says what a function takes and gives backaddVat :: Int -> Int
Compositionjoining two functions so the output of one feeds the nextf . g

The cells students fill in are left blank in this preview.

A function takes values and gives one back

Here is a function for a shop. addVat takes a price in pence and gives back the price with a fifth added. Its first line, with ::, is the type signature.

You call a function by writing its name, a space, then its arguments. There are no brackets and no commas. addVat 1000 means "apply addVat to 1000".

The shop file: two functions and their types

Code: haskell
addVat :: Int -> Int
addVat pence = pence + div pence 5

discount :: Int -> Int -> Int
discount percent pence = pence - div (pence * percent) 100

Save the shop file

Command
docker exec haskell sh -c "printf '%s\n' 'addVat :: Int -> Int' 'addVat pence = pence + div pence 5' '' 'discount :: Int -> Int -> Int' 'discount percent pence = pence - div (pence * percent) 100' > Shop.hs"

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

Add VAT to 1000 pence

Command
docker exec haskell ghc -e "addVat 1000" Shop.hs

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

Take 10 percent off 2000 pence

Command
docker exec haskell ghc -e "discount 10 2000" Shop.hs

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

Worked example: addVat 1000, step by step

StepExpressionValue
1pence1000
2div pence 5200 (whole-number division)
3pence + div pence 51200

The cells students fill in are left blank in this preview.

A type signature shows inputs and output

Read addVat :: Int -> Int as "addVat takes an Int and gives back an Int". An Int is a whole number. Other types are String, for text, and Bool, for True or False.

With two arguments, the signature has more arrows. Int -> Int -> Int takes two Ints and gives back an Int. The last type is always the answer.

Ask GHC for the type of addVat

Command
docker exec haskell ghc -e ":type addVat" Shop.hs

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

Ask GHC for the type of discount

Command
docker exec haskell ghc -e ":type discount" Shop.hs

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

Give discount only one argument

Command
docker exec haskell ghc -e ":type discount 10" Shop.hs

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

A pure function always gives the same answer

A pure function depends only on what it is given and changes nothing else. Call addVat 1000 today, tomorrow or a million times and you get 1200.

That makes a pure function easy to test and easy to trust. You can also join pure functions. Composition is written with a dot: f . g applies g first, then f.

Call the same function twice and compare

Command
docker exec haskell ghc -e "addVat 1000 == addVat 1000" Shop.hs

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

Discount first, then add VAT

Command
docker exec haskell ghc -e "(addVat . discount 10) 2000" Shop.hs

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

Worked example: addVat after discount 10

StepFunctionValue
1start2000
2discount 101800
3addVat2160

The cells students fill in are left blank in this preview.

A common mistake

Warning

Many people think a call needs brackets and commas, as in discount(10, 2000). In Haskell a space separates the function from its arguments: discount 10 2000. Brackets only group: addVat (discount 10 2000) applies addVat to the answer of discount.

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

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.