Part 15

Wrapping up: Indentation, Quiz, Cheatsheet

A note on indendation

The previous examples have been fancily indented. In Haskell indentation matters, a bit like in Python. The complete set of rules for indentation is hard to describe, but you should get along fine with these rules of thumb:

  1. Things that are grouped together start from the same column
  2. If an expression (or equation) has to be split on to many lines, increase indentation

While you can get away with using tabs, it is highly recommended to use spaces for all indenting.

Some examples are in order.

These all are ok:

i x = let y = x+x+x+x+x+x in div y 5

-- let and in are grouped together, an expression is split
j x = let y = x+x+x
                +x+x+x
        in div y 5

-- the definitions of a and b are grouped together
k = a + b
    where a = 1
          b = 1

l = a + b
    where
    a = 1
    b = 1

These are not ok:

-- indentation not increased even though expression split on many lines
i x = let y = x+x+x+x+x+x
in div y 5

-- indentation not increased even though expression is split
j x = let y = x+x+x
        +x+x+x
        in div y 5

-- grouped things are not aligned
k = a + b
    where a = 1
        b = 1

-- grouped things are not aligned
l = a + b
    where
    a = 1
        b = 1

-- where is part of the equation, so indentation needs to increase
l = a + b
where
    a = 1
    b = 1

If you make a mistake with the indentation, you’ll typically get a parse error like this:

Indent.hs:2:1: error: parse error on inputwhere

The error includes the line number, so just go over that line again. If you can’t seem to get indentation to work, try putting everything on just one long line at first.

Quiz

At the end of each section you’ll find a quiz like this. The quizes aren’t graded, they’re just here to help you check you’ve understood the chapter. You can check your answer by clicking on an option. You’ll see a green background if you were right, a red one if you were wrong. Feel free to guess as many times as you want, just make sure you understand why the right option is right in the end.

What is the Haskell equivalent of the C/Java/Python expression combine(prettify(lawn),construct(house,concrete))?

  1. combine prettify (lawn) construct (house concerete)
  2. combine (prettify lawn (counstruct house concrete))
  3. combine (prettify lawn) (construct house concrete)

What is the C/Java/Python equivalent of the Haskell expression send metric (double population + increase)?

  1. send(metric(double(population+increase)))
  2. send(metric(double(population)+increase))
  3. send(metric,double(population)+increase)
  4. send(metric,double(population+increase))

Which one of the following claims is true in Haskell?

  1. Every value has a type
  2. Every type has a value
  3. Every statement has a type

Which one of the following claims is true in Haskell?

  1. It’s impossible to reuse the name of a variable
  2. It’s possible to reassign a value to a variable
  3. An if always requires both then and else

What does the function f x = if even (x + 1) then x + 1 else f (x - 1) do?

  1. Maps every value x to the least even number greater than or equal to x
  2. Maps every value x to the greatest even number less than or equal to x
  3. Maps every value to itself

Why is 3 * "F00" not valid Haskell?

  1. 3 and "F00" have different types
  2. All numeric values need a decimal point
  3. "F00" needs the prefix “0x”

Why does 7.0 `div` 2 give an error?

  1. Because div is not defined for the type Double
  2. Because div is not defined for the type Int
  3. Because ... is used for delimiting strings.

Cheatsheet

To help you make the exercises and prepare for the exam, here is a handy cheatsheet with all concepts of part 15. Thanks to Daan Wichmann. Note that while this cheatsheet can help you to prepare for the exam, it is non-exhaustive, and your own responsibility that you go through all material.

-- Integer division
halve :: Int        -- type annotation
halve = 3 `div` 2   -- equation

-- Ordinary division
halfsy :: Double
halfsy = 5.0 / 2

-- Condintional expressions
price :: String -> Int
price product =
    if product == "milk"   -- note indentation: if it belongs to the rest, but want to split it on more lines, add an indent
        then 1
        else 2

-- Not equals operator
notFive :: Int -> Bool
notFive x = x /= 5

-- Boolean operators (and &&, or ||, ! not)
awesomeLecturer :: String -> Bool
awesomeLecturer lecturer = lecturer == "Emma" || lecturer == "Bryan"

-- Local definition (where; adds local def to definition)
greetings :: String
greetings = "Hello " ++ user
    where user = "Daan"

-- Local definition (let ... in; is an expression)
farewell :: String
farewell = let recipient = "Emma" in "See you soon " ++ recipient

-- Shadowing
getShadowed :: Int -> Int
getShadowed x = x where x = 5

-- Pattern matching and recursion
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

-- Pattern matching
hey :: String -> String -> String
hey "Dutch" "Daan" = "Hey, it's me"
hey "Dutch" name = "Hoi " ++ name
hey "English" name = "Hey " ++ name
hey "French" name = "Hé " ++ name
hey _ name = "Hi " ++ name

-- show
showIt :: Int -> String
showIt n = "This is the number " ++ show n

-- more recursion
fact :: Int -> Int
fact 1 = 1
fact n = n * fact (n - 1)
You have reached the end of this section!

You can check your current points from the blue blob in the bottom-right corner of the page.