diff --git a/lab/01-intro-lab.lhs b/lab/01-intro-lab.lhs
new file mode 100644
index 0000000000000000000000000000000000000000..da99d59e6e33db05753d375cedf5635ccbf23982
--- /dev/null
+++ b/lab/01-intro-lab.lhs
@@ -0,0 +1,127 @@
+\chapter{Einleitung}
+\begin{aufgabe}
+Zeigen Sie mehrere m"ogliche Auswertungen f"ur `hoch4 (2 + 3).
+
+> quadrat x = x * x
+
+> hoch4 x = quadrat (quadrat x)
+
+hoch4 (2+3)
+=
+hoch4 5
+=
+quadrat (quadrat 5)
+=
+quadrat (5 * 5)
+=
+quadrat 25
+=
+25*25
+=
+625
+
+hoch4 (2+3)
+=
+quadrat (quadrat (2+3))
+=
+quadrat (2+3) * quadrat (2+3)
+=
+(2+3)*(2+3) * (2+3)*(2+3)
+=
+5*5*5*5
+=
+625
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Definieren Sie eine Funktion `summe`, die eine
+Liste von Zahlen addiert.
+
+> summe :: [Integer] -> Integer
+> summe []     = 0
+> summe (x:xs) = x + summe xs
+
+Geben Sie einige Testf"alle an und vergleichen Sie mit der Standardfunktion
+`sum`.
+\end{aufgabe}
+
+\begin{aufgabe}
+Definieren Sie eine Funktion `laenge`, die die Laenge einer Liste berechnet.
+
+> laenge :: [Integer] -> Integer
+> laenge []     = 0
+> laenge (_:xs) = 1 + laenge xs
+
+Testfall:
+λ> laenge [1..5]
+5
+Finden Sie weitere Testf"alle und vergleichen Sie mit der Standardfunktion
+`length`.
+
+Vergleichen Sie mit der Definition aus der vorherige Aufgabe.
+\end{aufgabe}
+
+\begin{aufgabe}
+Zeigen Sie, dass `produkt [x] = x` f"ur beliebiges x gilt.
+
+produkt [x]
+= { [x] = x : [] }
+x * produkt []
+=
+x * 1
+=
+x
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Zeigen Sie eine Auswertung von `quick [3, 5, 2, 1, 4]`.
+
+quick [3, 5, 2, 1, 4]
+=
+quick [2,1] ++ [3] ++ quick [5,4]
+=
+quick [1] ++ [2] ++ quick [] ++ [3] ++ quick [4] ++ [5] ++ quick []
+quick [] ++ [1] ++ quick [] ++ [2] ++ [] ++ [3] ++ quick [] ++[4] + quick [] ++ [5] ++ []
+=
+[] ++ [1] ++ [] ++ [2] ++ [] ++ [3] ++ [] ++ [4] ++ [] ++ [5] ++ []
+=
+[1,2,3,4,5]
+
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Geben Sie die Funktion Fakult"at rekursiv an.
+
+> fakultaet' :: Integer -> Integer
+> fakultaet' 0 = 1
+> fakultaet' x = x * fakultaet' (x-1)
+
+Welches Problem gibt es bei Ihrer Definition?
+\end{aufgabe}
+
+\begin{aufgabe}
+Geben Sie eine Definition der Funktion der Fibonacci-Zahlen an.
+Zur Erinnerung: $f_0 = 0, f_1 = 1, f_n = f_{n-1} + f_{n-2}$
+
+> fibonacci :: Integer -> Integer
+> fibonacci 0 = 0
+> fibonacci 1 = 1
+> fibonacci x = fibonacci (x-1) + fibonacci (x-2)
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Definieren Sie die Funktionen `head` und `tail`, die das erste Element bzw.
+den Rest einer Liste ganzer Zahlen berechnen.
+
+> head' :: [Integer] -> Integer
+> head' (x:_) = x
+
+
+> tail' :: [Integer] -> [Integer]
+> tail' (_:xs) = xs
+
+\end{aufgabe}
diff --git a/lab/02-types.lhs b/lab/02-types.lhs
new file mode 100644
index 0000000000000000000000000000000000000000..66499ae0d0dca8cb302a887ace9720240846692b
--- /dev/null
+++ b/lab/02-types.lhs
@@ -0,0 +1,42 @@
+\chapter{Typen}
+
+> import Data.List
+
+\begin{aufgabe}
+Geben Sie den Typ der folgenden Ausdr"ucke an. Pr"ufen Sie Ihre Antwort mit GHCi.
+\begin{enumerate}
+\item [ 'o', 'h', 'm' ]
+\item ( 'o', 'h', 'm' )
+\item [ (), () ]
+\item [ ( 'o', ()), ('h', ())]
+\item ( ['o', 'h'], [(), ()] )
+\item [ 1, 3.14, 6.5 ]
+\item ( 1, 3.14, 6.5 )
+\item [ head, last, (!! 2) ]
+\end{enumerate}
+\end{aufgabe}
+
+\begin{aufgabe}
+Schreiben Sie eine Definition, die den folgenden Typ hat:
+\begin{enumerate}
+\item zahlen :: [Integer]
+\item wahrheiten :: [[Bool]]
+\item add :: Int -> Int -> Int -> Int
+\item zip3' :: [a] -> [b] -> [c] -> [(a, b, c)]
+\item apply :: (a -> b) -> a -> b
+\end{enumerate}
+Bei welchen Typen gibt es nur eine L"osung?
+\end{aufgabe}
+
+\begin{aufgabe}
+Geben Sie den Typ der folgenden Funktionen an:
+\begin{enumerate}
+\item second xs = head (tail xs)
+\item swap (x, y) = (y, x)
+\item pair x y = (x, y)
+\item palindrome xs = reverse xs == xs
+\item twice f x = f (f x)
+\end{enumerate}
+Geben Sie auch die Klassenconstraints an, sovern ueberladene Operatoren
+verwendet werden.
+\end{aufgabe}
diff --git a/lab/03-functions.lhs b/lab/03-functions.lhs
new file mode 100644
index 0000000000000000000000000000000000000000..ce191b3d55dfff43af69605e661a88db2a42bc1e
--- /dev/null
+++ b/lab/03-functions.lhs
@@ -0,0 +1,89 @@
+\chapter{Funktionen}
+\begin{aufgabe}
+Weshalb kann im allgemeinen der Funktionstyp keine Eq Instanz besitzen? Wir
+betrachten zwei Funktionen als gleich, wenn sie vom gleichen Typ sind (!) und
+f"ur stets f"ur gleiche Eingaben auch gleiche Ergebnisse liefern. Diese
+Eigenschaft hei"st extensionale Gleichheit der Funktion.
+\end{aufgabe}
+
+\begin{aufgabe}
+Verwenden Sie Funktionen aus Data.List, um die Funktion
+
+> halbieren :: [a] -> ([a], [a])
+> halbieren = undefined
+
+zu schreiben, die eine Liste gerader L"ange in der Mitte teilt. Finden sie
+f"ur ungerade L"ange eine sinnvolle Spezifikation.
+
+Schreiben Sie nun eine Funktion, die zwei sortierte Listen zu einer sortierten
+Liste verschmilzt.
+
+> merge :: Ord a => ([a],[a]) -> [a]
+> merge = undefined
+
+Schreiben Sie nun unter Verwendung der beiden Funktionen halbieren und merge
+eine Funktion mergesort.
+
+> mergesort :: Ord a => [a] -> [a]
+> mergesort = undefined
+
+\end {aufgabe}
+
+\begin{aufgabe}
+Definieren Sie die Funktion third :: [a] -> a, die das dritte Element einer
+Liste liefert, wenn es existiert, mittels:
+\begin{enumerate}
+\item head und tail,
+\item dem Listenindexoperator !!,
+\item Patternmatch.
+\end{aufgabe}
+
+\begin{aufgabe}
+Schreiben Sie eine sichere tail Funktion, die sich bei einer nichtleeren Liste
+verh"alt wie tail und bei einer leeren Liste, eine leere Liste zur"uck gibt.
+Verwenden Sie, wenn erforderlich die Funktionen tail und null :: [a] -> Bool,
+um safetail zu definieren:
+\begin{enumerate}
+\item mit einem bedingten Ausdruck,
+\item mit guarded equations
+\item mit pattern matching
+\end{enumerate}
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Geben Sie wie in der Vorlesung vier verschiedene Wege an, um die Disjunktion
+(oder) auf Bool zu implementieren.
+\end{aufgabe}
+
+\begin{aufgabe}
+Betrachten Sie den folgenden Datentyp f"ur eine dreiwertige Logik:
+
+> data Drei = Nein | Jein | Ja
+>   deriving (Show, Eq)
+
+Geben Sie zunaechst mit der "Wahrheitstabellen"-Methode eine Definition
+f"ur die Funktionen not, and und or. Ueberlegen Sie sich, was der Wert
+Jein bedeutet und definieren Sie die Funktionen dann entsprechend.
+
+> tnot :: Drei -> Drei
+> tnot = undefined
+
+> tand :: Drei -> Drei -> Drei
+> tand = undefined
+
+> tor :: Drei -> Drei -> Drei
+> tor = undefined
+
+Betrachten Sie die Wahrheitstabelle und finden Sie eine kompaktere Definition
+mit Patterns f"ur and:
+
+> tand' :: Drei -> Drei -> Drei
+> tand' = undefined
+
+Finden Sie eine kompaktere Definition f"ur or, indem Sie Guards verwenden.
+
+> tor' :: Drei -> Drei -> Drei
+> tor' = undefined
+
+\end{aufgabe}
diff --git a/lab/04-comprehensions.lhs b/lab/04-comprehensions.lhs
new file mode 100644
index 0000000000000000000000000000000000000000..ee27ab9c42132d85b88d3944a8c2610d2d09ef25
--- /dev/null
+++ b/lab/04-comprehensions.lhs
@@ -0,0 +1,53 @@
+\chapter{List Comprehensions}
+
+\begin{aufgabe}
+Schreiben Sie eine Funktion, die alle pythagoreischen Zahlentripel bis zu
+einer maximalen Gr"o"se n ausgibt. Achten Sie darauf, dass keine doppelten
+Tripel (z. B. (3,4,5) ~ (4,3,5) ) vorkommen. Verwenden Sie eine List
+Comprehension. Zur Erinnerung: \[ a^2 + b^2 = c^2 \].
+
+> pythagoras :: Integer -> [(Integer, Integer, Integer)]
+> pythagoras n = [(a, b, c) | a <- [1..n], b <- [a..n], c <- [b..n], a^2 + b^2 == c^2]
+
+\end{aufgabe}
+
+\begin{aufgabe}
+
+Schreiben Sie eine Funktion, die alle Quadrupel bis zu einer maximalen Gr"o"se ausgibt, die folgende Gleichung erf"ullen:
+\[ a^2 + b^2 = c^2 + d^2 \].
+
+Vermeiden Sie wie in der vorherigen Aufgabe Quadrupel, die im wesentlichen
+gleich sind.
+
+> quadratsummen :: Integer -> [(Integer, Integer, Integer, Integer)]
+> quadratsummen n = [(a, b, c, d) | a <- [1..n], b <- [a..n], c <- [b..n], d <- [c..n], a^2 + b^2 == c^2 + d^2]
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Schreiben Sie die Funktion replicate aus Data.List als List Comprehension.
+
+> replicate' :: Int -> a -> [a]
+> replicate' n x = [x | _ <- [1..n]]
+
+\end{aufgabe}
+
+\begin{aufgabe}
+
+Formulieren Sie das Skalarprodukt zweier Vektoren, die als Liste implementiert
+sind. Verwenden Sie an geeignerter Stelle eine List Comprehension.
+
+\[ x * y = \sum_{i=0}^{n-1}(x_i * y_i) \]
+
+> skalar :: [Double] -> [Double] -> Double
+> skalar x y = sum [ x_i * y_i | (x_i, y_i) <- zip x y]
+
+\end{aufgabe}
+
+\begin{aufgabe}
+Schreiben Sie die Funktion partition aus Data.List als List Comprehension.
+
+> partition' :: (a -> Bool) -> [a] -> ([a], [a])
+> partition' p xs = ([x | x <- xs, p x], [x | x <- xs, not (p x)])
+
+\end{aufgabe}