In this first part of the course, we will provide an overview of the Haskell language, introducing briefly all the most important concepts that set Haskell apart from other programming language.
All these concepts will be discussed in greater detail in the other parts of the course.
Accompanying materials
1–1 Welcome
In this video, I, Andres Löh, the lecturer of this course, introduce myself, and I explain the structure of the course.
Self Test
- For every video, there will be a few “self test” exercises. These, you should be able to easily do if you have watched and understood the video. You do not have to submit these exercises, but if you have difficulties doing them, or are uncertain whether you have done them correctly, it is a clear indication that you should ask for help.
1–2 Expressions
Expressions are – in essence – possibly nested terms built from constants and functions calls and form probably the most important part of the Haskell language.
In this video, we introduce expressions by example, and discuss the syntax of function calls.
Self Test
Start GHCi and type in some examples from this video. Convince yourself that you get the same results.
What is the result of typing
replicate 3 'x'
into GHCi?
1–3 Types
Haskell is a statically typed language, and types play and important role. We introduce the some widely used types and discuss how function types make use of currying.
The type system comes with many features that enable code reuse, such as parametric polymorphism and overloading. Both are briefly discussed in this video.
We also briefly mention how Haskell handles code that has side effects, namely by making side effects visible in the type system.
Self Test
Start GHCi and type in some examples from this video. Convince yourself that you get the same results.
What is the result of
:t words
in GHCi? Try to figure out what the functionwords
does by applying it to some inputs.Note that GHCi has a
:doc
command. Try:doc words
. Does the explanation given match what you’ve been figuring out?What do you think the type of
replicate
is, based on your experiences in the self-test questions of the previous video? Does the:t
command confirm your expectations?
1–4 Datatypes and Functions
We discuss how to make bindings to define new constants and functions. We also discuss how to introduce a new simple enumeration type and how to define a function that operates on this type by means of pattern matching.
Self Test
Open an editor, make the binding for
double
as shown in the video, save the source file, load the file into GHCi, and successfully calldouble 5
to obtain the result10
.Make a binding
triple
in the same source file that triples a number according to the same principle asdouble
, and test it in GHCi.Type in the
distance
function into your source file as shown in the video, including the type signature. Use the function in GHCi after reloading, and also try:t distance
to see that the inferred type matches the specified type signature.Type in the datatype
Choice
as shown in the video, including thederiving
clause, and define a functionworsen
according to the same principles asimprove
that mapsRock
toScissors
,Paper
toRock
, andScissors
toPaper
.Convince yourself that for all elements
x
of typeChoice
, callingworsen (improve x)
yieldsx
again.
1–5 Pattern Matching
We continue our discussion of pattern matching and define functions via pattern matching on Booleans and lists. We introduce our own list type to understand the structure of Haskell’s built-in lists better.
Self Test
Try to define the logical and operator
(&&)
by pattern matching, similar to how we defined(||)
in the video.Implement the
List
datatype as shown in the video, and implement theelem
function both on theList
datatype and on the type of built-in lists, both as shown in the video.By modifying the
elem
function, can you turn it into a function that checks whether all elements in the list are equal to the given element?
1–6 Equational Reasoning and Lazy Evaluation
We demonstrate how to reason about evaluation by performing step-by-step reduction, so-called equational reasoning. We also see how Haskell always selects the outermost function call for reduction, implying that function arguments are only actually evaluated when required to make progress.
Self Test
Try
take 10 [1..]
and observe that it works.Try
[1..]
and stop evaluation with Ctrl+C.What does
takeWhile (\ x -> x < 100) (map (\ x -> x * x) [1..])
do?