Database Research Group

WSI – Database Systems Research Group

Functional Programming


News
  • Jan 14, 2020 — Die Übungsstunde zu Functional Programming heute Nachmittag 14-16 Uhr muss leider wegen Krankheit entfallen. Fragen zum aktuellen Übungsblatt können im Forum weiterhin gestellt werden. — Benjamin Dietrich


Numbers are values. Strings are values. Booleans are values. In Functional Programming, functions simply are simply values as well. This view on programming leads to an elegant and expressive programming paradigm which we will investigate in this course. During the course, we will use the programming language Haskell. The majority of the concepts we will consider applies in other (functional) languages as well.

Participants are not expected to be fluent in Haskell from the beginning. We will spend the first three weeks of the semester on a Haskell Ramp-Up. Things will progress rather fast, though. The majority of the semester will be used for the good stuff: intermediate and advanced topics, of which there are plenty.

Syllabus

This course will provide an introduction to Haskell (first half) and then touch on intermediate-level topics. We will discuss (topics in parentheses will be addressed if we'll find the time):

  • Values and types
  • Function definitions (guards, pattern matching)
  • List processing
  • Algebraic data types
  • Type classes
  • Domain-specific languages (DSLs; shallow and deep embedding)
  • Laziness
  • Functors. Applicative Functors, Monads
  • (Monadic parsing)
  • (Applications: breadth-first search, path finding)

Forum

Discussion around this course and Haskell in general are encouraged in the forum. ⚠️ If you want to participate in the exercises, you absolutely need to register in the forum, as we use it to create/administer student accounts in this course. Thus, please stop by regularly, have a look, and say "hi".

Tutorial and Exercises

  • We will provide weekly exercise sheets (hand-out: Friday, hand-in by Thursday night).

  • You are admitted to the final exam if you score at least ⅔ of the overall exercise points.

  • Scoring well in the exercises leads to bonus points in the final exam.

Haskell (GHC, Haskell Platform)

The course will use the de-facto standard Haskell compiler GHC and its interactive variant (also known as read-eval-print loop or REPL) GHCi. We strongly suggest you download and install the so-called Haskell Platform which includes both GHC and GHCi (and more). Available for virtually all operating systems, including Windows, Linux, macOS. Make sure to install the recent version.

Literature

The following introductory books and courses on Haskell are recommend reading — some of these are available online:

We will refer to additional material for the individual topics during the semester.


Slides
NrChapterDownload
1

Welcome + Haskell Ramp-Up

Reduction, values, types, expressions, function definitions

pdf
2

Haskell Ramp-Up (Part 2)

Algebraic data types, type classes

pdf
3

Domain-Specific Languages (DSLs)

Modules, abstract data types, shallow + deep embedding of DSLs

pdf
4

Lazy Evaluation

Reduction, weak head normal form (WHNF), infinite lists

[updated Dec 5, 2019: simplified isort]

pdf
5

Functors and Applicatives

Haskell's type classes Functor and Applicative (also: kinds and Monoids)

pdf
6

Monads

Haskell's type class Monad, the "programmable semicolon"

pdf
Additional material (code, data)
NrFileDownload
1chewie.hs

The Hello, World! of Haskell.

  1. Compile with Haskell compiler ghc via ghc --make chewie.hs, execute on the command line with ./chewie.
  2. Load into REPL ghci via ghci chewie.hs, then evaluate function main.
hs
2isPrime.hs

Prime number test. Efficient thanks to lazy evaluation of factors (a comparison with the empty list [] can be decided once the first element of factors has been found).

hs
3infix-op.hs

Demonstrates the definition of user-defined operator ~=~.

hs
4factorial.hs

Compute the factorial n! of natural number n. Defines two equivalent variants of the function that demonstrate the use of conditional expressions (if...then...else...) and guards.

hs
5power.hs

Two equivalent formulations of an efficient power computation. Demonstrates the use of guards, local definitions (where, let … in) and explicit layout syntax using {,} and;.

hs
6bits.hs

A demonstration of type synonyms (type t₁ = t₂) and list processing (determine the bit list of an Integer value).

hs
7sum.hs

A reimplementation of the sum built-in function: sum all elements of a list. Two formulations: guards and pattern matching.

hs
8take.hs

A reimplementation of the built-in take function: extract a prefix (of given length) from a list.

hs
9mergesort.hs

An implementation of MergeSort in Haskell. Builds on the merge function developed in the lecture.

hs
10deriving.hs

Definition of and functions over sum data types (Weekday, Move, Outcome). Uses deriving to define basic operations like equality, ordering, showing, ...

hs
11sequence.hs

Definition and functions over product type Sequence.

hs
12cons.hs

Defines algebraic data type List a and shows that it is isomorphic to the builtin type constructor [a]. Uses lifting to lift regular list-processing functions from [a] to List a.

hs
13eval-compile-run.hs

Defines abstract syntax trees for simple arithmetic expressions Exp a and implements an interpreter (≡ evaluation function eval), compiler (compile) and mini stack-based virtual machine (run).

Interpreter as well as compiler and VM are related:

∀ e :: Num a => Exp a: (run [] . compile) e == eval e

hs
14searchFor.hs

Function searchFor performs a lookup in a key/value-dictionary, provided that the key type supports equality comparisons.

(An equivalent function is already built into Haskell's Prelude: lookup.)

hs
15library-exposed.hs

First version of the IntegerSet DSL with fully exposed implementation details. 🙁

hs
16set-language-shallow.hs

Imports module SetLanguageShallow (or SetLanguageShallowCard) to demonstrate that representation details remain hidden.

hs
17SetLanguageShallow.hs (module)

Re-implementation of the IntegerSet DSL with representation details (characteristic functions with type Integer -> Bool) hidden inside a module.

Module is imported by set-language-shallow.hs.

hs
18SetLanguageShallowCard.hs (module)

A shallow embedding of IntegerSet based on characteristic functions. This module includes a cardinality observer for sets.

hs
19set-language-deep.hs

Imports module SetLanguageDeep (or SetLanguageDeepCard) to demonstrate a deep embedding of the integer set DSL.

hs
20SetLanguageDeep.hs (module)

A deep embedding of IntegerSet.

hs
21SetLanguageDeepCard.hs (module)

A deep embedding of IntegerSet. This module includes a cardinality observer for sets.

hs
22ExprDeep.hs (module)

A simple deeply embedded DSL over values of type Integer and Bool. Permits the construction of il-typed expressions.

hs
23expr-language.hs

Imports module ExprDeep and builds one well-typed and one ill-typed expression.

hs
24ExprDeepGADTTyped.hs (module)

Uses GADTs to define a deeply embedded DSL over Integer and Bool values that detects ill-typed expressions at compile time.

hs
25expr-language-typed.hs

Imports module ExprDeepGADTTyped and demonstrates the well-typed construction and evaluation of expressions.

hs
26ExprEmbeddings.hs

Define type class Expr a that describes a simple language over Integers with let...in-bindings. Three instances of this class define two shallow and one deep embedding of this language.

[ Additional material — not discussed in the lecture. ]

hs
27expr-embeddings.hs

Imports module ExprEmbeddings to test all three instances of the Expr a language.

[ Additional material — not discussed in the lecture. ]

hs
28PatternMatching.hs

Defines a DSL that describes string patterns. Pattern matching returns (a possible empty) list of matches:

type Pattern a = String -> [(a, String)]
                    ↑        ↑     ↑
                input     result   residual string
hs
29pattern-matching.hs

Imports module PatternMatching to test-drive the pattern matchers.

hs
30normal-order.hs

Demonstrates that normal order reduction finds the normal form of an expression regardless of the presence of undefined values (function bomb has value ⊥).

hs
31sharing.hs

Uses trace (module Debug.Trace) to demonstrate that Haskell employs graph reduction (redex sharing) during evaluation.

hs
32bottom.hs

Demonstrates the strict semantics of pattern matching in Haskell.

hs
33min=head-isort.hs

Implements list minimum as the composition head . isort to demonstrate that lazy evaluation (to WHNF) can make declarative specifications of algorithms efficient to execute.

Caveat: this depends on the interaction of head and isort and does not work for arbitrary sorting algorithms.

hs
34newton-raphson.hs

Modular program whose parts communicate via infinite lists.

Approximate the square root of x using the Newton-Raphson series. Composes iterate with within, where the latter inspects a finite prefix of the potentially infinite list generated by the former. Haskell's evaluation to WHNF glues both together so that a result is produced in finite time.

hs
35numerical-integration.hs

Modular program whose parts communicate via infinite lists.

Approximate the square of function f within interval [x₁,x₂]. Divide the interval until f is close to linear in the subdivision. Keep subdividing until the sum of subdivided integrals converges. Interval subdivision (subdivide) keeps generating new integral approximations until test within decides that we have reached the desired accuracy.

hs
36flagged-status.hs

Demonstrates the use of partially applied binary type constructors to form new unary type constructors:

type Flagged = (,) Bool
hs
37round.hs

Builds on the fact that Either String is an instance of Functor to build a composition of functions that propagates error messages.

hs
38stacked-functors.hs

Use a growing chain of fmap compositions to "reach into" and manipulate a complex value at desired depth in a nested value build out of functors.

hs
39break-the-law.hs

Defines a Functor instance for an algebraic data type (a deeply embedded DSL over Booelans) and demonstrates that functor laws are satisfied/violated when we get the implementation of fmap right/wrong.

hs
40apples-oranges-newtypes.hs

Use Haskell's newtype to create specific variants of existing types. No runtime overhead!

hs
41Validation.hs

(Module) Represent computations that are accompanied with an error context. Defines Functor and Applicative instances.

hs
42validate.hs

Uses module Validation.hs to perform username/password validation that is not cluttered with error log accumulation.

hs
43sequence-Maybe.hs

Defines the (>=>) left-to-right composition operator (Kleisli composition) for partial functions of type a -> Maybe b and puts that to use.

hs
44sequence-Either.hs

Defines the (>=>) left-to-right composition operator (Kleisli composition) for exception-generating functions of type a -> Exc ba -> Either Error b and puts that to use.

hs
45sequence-ST.hs

Defines the (>=>) left-to-right composition operator (Kleisli composition) for stateful functions of type a -> ST ba -> State -> (State, b) and puts that to use.

hs
46monadic-Maybe.hs

Define a composition based on partial functions a -> Maybe b based on the Monad instance for Maybe. Sequencing is based on monadic bind ((>>=)). Compare this to file sequence-Maybe.hs.

hs