Compare commits

..

18 Commits

Author SHA1 Message Date
Julian Ospald f335b3a522
Hide subsubsections in initial TOC 2015-04-23 23:04:07 +02:00
Julian Ospald 1975e27e5c
Improve subsection titles 2015-04-23 22:06:23 +02:00
Julian Ospald 3cfdec16ed
Use footnotes for urls 2015-04-23 22:02:44 +02:00
Julian Ospald c504fba841
VL2: translate into german 2015-04-23 21:34:47 +02:00
Julian Ospald 913900a9e8
VL1: Übersetzung ins Deutsche 2015-04-23 02:06:32 +02:00
Julian Ospald 91330daea8
Rm reference to polymorphic data types 2015-04-21 18:35:29 +02:00
Julian Ospald 5acabb296f
Fix 'clean' target 2015-04-21 18:05:23 +02:00
Julian Ospald 198ccedcf5
Improve wording 2015-04-21 18:05:07 +02:00
Julian Ospald ab7c101b4b
Rm obsolete reference to ADTs 2015-04-21 14:42:05 +02:00
Julian Ospald 4f67c48b6f
Fix polymorphism since the ADT section of VL1 is gone 2015-04-21 14:28:01 +02:00
Julian Ospald d9750e6b34
Rm obsolete slides 2015-04-21 14:27:26 +02:00
Julian Ospald 5b4be12e0b
Add case...of code 2015-04-21 14:14:24 +02:00
Julian Ospald 9dc7adaaf3
Add missing toc slide 2015-04-21 14:14:12 +02:00
Julian Ospald 1838c3276f
Fix \slide command to include subsubsection numbering 2015-04-21 14:13:56 +02:00
Julian Ospald 02a33a44fe
Improve "how to think haskell" 2015-04-21 14:07:57 +02:00
Julian Ospald 361af10451
Add case...of slide, rename slides 2015-04-21 14:07:42 +02:00
Julian Ospald e315e78b39
Adjust questions, because we omitted the ADT section 2015-04-21 13:46:31 +02:00
Julian Ospald efc0f586ed
Rm ADT section as discussed with Prof Gips 2015-04-21 13:46:08 +02:00
41 changed files with 75 additions and 237 deletions

View File

@ -90,24 +90,6 @@
\slide{./content/VL1_pairs.tex}
\subsection{\ifger{Algebraische Datentypen}{Algebraic Data Types}}
\slidetoc
\slide{./content/VL1_ADT1.tex}
\slide{./content/VL1_ADT2.tex}[ (cnt.)]
\slide{./content/VL1_ADT3.tex}[ (cnt.)]
\slide{./content/VL1_ADT4.tex}[ (cnt.)]
\subsubsection{Trees}
\slide{./content/VL1_ADT5.tex}
\slide{./content/VL1_ADT6.tex}[ (cnt.)]
\subsubsection{ADTs \ifger{allgemein}{generalized}}
\slide{./content/VL1_ADT7.tex}
\section{Résumé}
\slidetoc

View File

@ -1,20 +0,0 @@
\ifger{Natürlich können wir auch unsere eigenen Datentypen definieren. Ein sehr häufiger Typ ist die \emph{Enumeration}. Z.b. können wir den Wochentag definieren als:}{Of course we can also define our own data types in haskell. One very common type is the \emph{enumeration}. For example, we could define a data type for the Week:}
\begin{haskellcode}
data WeekDay = Monday
| Tuesday
| Thursday
| Wednesday
| Friday
| Saturday
| Sunday
\end{haskellcode}
\ifger{Dies erzeugt den neuen Datentyp}{This creates the new data type} \hinline{WeekDay} \ifger{mit}{with} 7 \emph{\ifger{Konstruktoren}{constructors}}. \ifger{Das bedeutet, dass}{That means} \hinline{Monday}, \hinline{Tuesday} etc. \ifger{alles Werte vom Typ}{are all values of the type} \hinline{WeekDay}\ifger{ sind.}{.}
\pause
\\
\ifger{Jetzt können wir auch eine ganze Woche definieren mittels einer Liste:}{We could now define a whole week, by creating a list:}
\pause
\begin{haskellcode}
week :: [WeekDay]
week = [Monday, Tuesday, Thursday, Wednesday
, Friday, Saturday, Sunday]
\end{haskellcode}

View File

@ -1,7 +0,0 @@
\ifger{Und auch auf unserem \hinline{WeekDay} Typ können wir \emph{pattern matchen}. Wir wollen z.B. herausfinden, ob ein gegebener Tag ein Montag ist:}{And we can again \emph{pattern match} on our \hinline{WeekDay} type. Let's find out if a given day is a Monday:}
\pause
\begin{haskellcode}
isMonday :: WeekDay -> Bool
isMonday Monday = True
isMonday x = False
\end{haskellcode}

View File

@ -1,14 +0,0 @@
\ifger{Wir können natürlich auch mehr als nur Enumerationen. Wie wäre es mit Fehlerbehandlung? Z.B. wollen wir eine Funktion, die einen Int zurückgibt, aber falls etwas schief gelaufen ist wollen wir nicht einfach nur eine 0 oder einen magischen Wert, sondern eine richtige Fehlernachricht zurückgeben:}{But we can do more than enumerations. How about we do some error handling? Let's say we want a function to return an \hinline{Int}, but in case something went horribly wrong, we don't just want to return a 0 or some magic number, but a proper error message. Here we go:}
\pause
\begin{haskellcode}
data MaybeInt = NoError Int
| Error String
\end{haskellcode}
\pause
\ifger{D.h. Konstruktoren sind auch gewöhnliche \emph{Funktionen}! Und sie können Argumente haben, genau wie Funktionen. Hier ist die Typsignatur:}{So constructors are just \emph{functions}! And they can have arguments, just like functions. Let's check their types:}
\begin{haskellcode}
> :t NoError
NoError :: Int -> MaybeInt
> :t Error
Error :: String -> MaybeInt
\end{haskellcode}

View File

@ -1,15 +0,0 @@
\ifger{Und jetzt können wir Sicherheitsabfragen machen:}{And now we can do sanity checks:}
\begin{haskellcode}
calcSomething :: Int -> MaybeInt
calcSomething x
| x < 100 = NoError (x * 5)
| otherwise = Error "Int out of range!"
\end{haskellcode}
\pause
\ifger{Und darauf \emph{pattern matchen}}{And pattern match on it as well}:
\begin{haskellcode}
addIntToList :: MaybeInt -> [Int]
addIntToList (NoError x) = [x]
addIntToList (Error str) = []
\end{haskellcode}
\ifger{D.h. wenn wir hier einen Error bekommen, geben wir einfach eine leere Liste zurück. Ansonsten geben wir die Liste mit dem \hinline{Int} als einziges Element zurück.}{So if we got an error, we just return an empty list, otherwise we return a list with the \hinline{Int} as its only element.}

View File

@ -1,23 +0,0 @@
\ifger{Jetzt wollen wir etwas komplexere ADTs definieren. Z.b. einen Tree:}{Let's define something more complex. How about a tree?}
\pause
\begin{haskellcode}
data Tree = Leaf Char
| Node Tree Int Tree
\end{haskellcode}
\ifger{Verwirrt? Schauen wir genauer hin.}{Uh... that looks mean. Let's examine this.}\\
\pause
\ifger{Wir haben}{We have}:
\begin{itemizep}
\item \ifger{den Datentyp \hinline{Tree} definiert}{defined a data type \hinline{Tree}}
\item \ifger{einen Konstruktor \hinline{Leaf} vom Typ \hinline{Tree} mit einem Argument vom Typ \hinline{Char}}{a constructor \hinline{Leaf} of type \hinline{Tree} with one arguments of type \hinline{Char}}
\item \ifger{einen Konstruktor \hinline{Node} vom Typ \hinline{Tree} mit 3 Argumenten}{a constructor \hinline{Node} of type \hinline{Tree} with 3 arguments}
\begin{itemizep}
\item \hinline{Tree}
\item \hinline{Int}
\item \hinline{Tree}
\end{itemizep}
\end{itemizep}
\slidep
\ifger{Das bedeutet: ein \hinline{Tree} kann entweder ein \hinline{Leaf} oder eine interne \hinline{Node} sein mit 2 Subtrees. Wollen wir einen \hinline{Leaf} erzeugen, müssen wir dem Konstruktor einen \hinline{Char} übergeben. Wollen wir eine \hinline{Node} bauen, müssen wir 3 Argumente in Reihenfolge übergeben: ein weiterer \hinline{Tree}, ein \hinline{Int} und noch ein \hinline{Tree}.}{That means: a \hinline{Tree} can either be a \hinline{Leaf} or an internal \hinline{Node} with two sub-trees. If we want to create a \hinline{Leaf}, we have to pass the constructor a \hinline{Char}. If we want to create a \hinline{Node}, we have to pass 3 arguments, in order: another \hinline{Tree}, an \hinline{Int} and yet another \hinline{Tree}.}\\
\ifger{D.h. wir können Informationen sowohl in den leafs (\hinline{Char}) als auch in den internen nodes (\hinline{Int}) speichern. Dies ist nur ein Beispiel.}{So we can save information in the leafs (\hinline{Char}) and in the internal nodes (\hinline{Int}).\\
This is just an example. There are endless more ways of trees.}

View File

@ -1,13 +0,0 @@
\ifger{Wir bauen unseren Tree:}{Let's build our tree:}
\begin{haskellcode}
tree :: Tree
tree = Node
(Leaf 'x')
1
(Node
(Leaf 'y')
2
(Leaf 'z')
)
\end{haskellcode}
\ifger{Siehe Tafel...}{See board...}

View File

@ -1,7 +0,0 @@
\ifger{D.h. wenn wir verallgemeinern müssten, hat ein algebraischer Datentyp einen oder mehr \textbf{Konstruktoren}, von denen jeder null oder mehr \textbf{Argumente} hat. Z.B.:}{So if we want to generalize it, an algebraic data type has one or more \textbf{constructors}, and each of them can have zero or more \textbf{arguments}. E.g.:}
\begin{haskellcode}
data AlgDataType = Constr1 Type11 Type12
| Constr2 Type21
| Constr3 Type31 Type32 Type33
| Constr4
\end{haskellcode}

View File

@ -4,6 +4,5 @@
> 6 * 5.0
> "Hello" ++ " world"
> "Haskell" > "C++"
> 3 > 4
> True && False
\end{haskellcode*}

View File

@ -5,5 +5,5 @@
\item \ifger{da das Typsystem extrem mächtig ist, sind die Fehlermeldungen des type-checkers manchmal verwirrend und zeigen nicht immer den Fehler, den man erwartet hätte}{because the type system is extremely powerful/complex, type error messages can be very confusing and don't always show the error you expected}
\item \ifger{(noch) keine premium-IDE mit allen möglichen features}{no premium-like IDE with every possible feature (yet)}
\item \ifger{dynamisches linking ist noch WIP und man hat sehr häufig ABI-Inkompatibilität}{dynamic linking is sort of WIP yet, lots of ABI breakage}
\item \ifger{da der Großteil der IT in imperativen Programmiersprachen denkt, ist es häufig schwierig pseudo-code für funktionale Sprachen zu finden, weshalb man letztendlich Algorithmen reverse-engineeren muss}{because most of the world thinks in imperative style languages, it's often difficult to find pseudo-code for functional style languages, so you end up reverse-engineering algorithms}
\item \ifger{da der Groteil der IT in imperativen Programmiersprachen denkt, ist es häufig schwierig pseudo-code für funktionale Sprachen zu finden, weshalb man letztendlich Algorithmen reverse-engineeren muss}{because most of the world thinks in imperative style languages, it's often difficult to find pseudo-code for functional style languages, so you end up reverse-engineering algorithms}
\end{itemizep}

View File

@ -14,7 +14,6 @@ GHCi...
\vspace{\baselineskip}
\\
\ifger{Was ist eine mögliche Typsignatur dieser Funktion?}{What is a possible type signature for this function?}
\pause
\begin{haskellcode}
f :: Int -> Int
f x = x * x

View File

@ -8,7 +8,4 @@ sumPair :: (Int, Int) -> Int
sumPair (x, y) = x + y
\end{haskellcode}
\pause
\ifger{Hinweis: wir benutzen}{Note: we use} \hinline{(x, y)} \ifger{als Notation sowohl für den Typ als auch die Definition! Dies sind trotzdem 2 verschiedene Dinge. Wir können auch Triple, Quadruple etc. haben.}{notation for both the type and the definition! Those are still two different things. We can also have triples, quadruples etc.}
\vspace{\baselineskip}\\
\pause
\ifger{Frage: Unterschied zu Listen?}{Question: difference to lists?}
\ifger{Hinweis: wir benutzen}{Note: we use} \hinline{(x, y)} \ifger{als Notation sowohl für den Typ als auch die Definition! Dies sind trotzdem 2 verschiedene Dinge. Wir können auch Triple, Quadruple etc. haben.}{notation for both the type and the definition! Those are still two different things. We can also have triples, quadruples etc.}

View File

@ -6,7 +6,7 @@ isZero 0 = True
isZero x = False
\end{haskellcode}
\vspace{\baselineskip}
\ifger{D.h. wenn wir eine \hinline{0} übergeben, bekommen wir \hinline{True} zurück. Wenn wir keine \hinline{0} übergeben, dann bekommen wir \hinline{False} zurück, denn \hinline{x} in Zeile 3 ist ebenso pattern matching, allerdings matcht es jede Zahl.}{So if we pass it \hinline{0}, we get \hinline{True}. If we do not pass \hinline{0}, we get \hinline{False}, because \hinline{x} in line 3 is pattern matching as well, but matches every Int.}
\ifger{D.h. wenn wir eine \hinline{0} übergeben, bekommen wir \hinline{True} zurück. Wenn wir keine \hinline{0} übergeben, dann bekommen wir \hinline{False} zurück und der Eingabewert wird quasi nicht weiter betrachtet.}{So if we pass it \hinline{0}, we get \hinline{True}. If we do not pass \hinline{0}, we get \hinline{False} and the value we passed gets basically ignored.}
\vspace{\baselineskip}
\\
\pause

View File

@ -1,3 +1,3 @@
\begin{itemizep}
\item {laziness}
\item \ifger{keine}{none}...
\end{itemizep}

View File

@ -3,16 +3,14 @@
\item \ifger{was ist referenzielle Transparenz?}{What is referential transparency?}
\item \ifger{kann ich referenzielle Transparenz mit Seiteneffekten haben?}{Can you have referential transparency with side effects?}
\item \ifger{wovon hängt die Ausgabe einer Haskell Funktion ab?}{What does the output of a haskell function depend on?}
\item \ifger{Was ist call-by-name? Was ist call-by-need?}{What is call-by-name? What is call-by-need?}
\item \ifger{was ist}{What is} laziness?
\item \ifger{Wann werden Typen in Haskell geprüft?}{When are types checked in haskell?}
\item \ifger{Was sind die Unterschiede zwischen Listen und Tuplen?}{What are the differences between lists and pairs?}
\end{itemize}
\ifger{Ist dies eine \emph{total} oder eine \emph{partial} Funktion? Wie müsste man sie eventuell umschreiben?}{Is this a total or a partial function? Would you extend it? How?}
\begin{haskellcode}
data IntOrDouble = MkDouble Double
| MkInt Int
f :: Int -> IntOrDouble
f 0 = 0.5
even :: Int -> Bool
f 0 = True
f 2 = True
f 4 = True
\end{haskellcode}

View File

@ -2,6 +2,7 @@
\begin{itemize}
\item \textbf{GHC}: \ifger{das ist der Haskell Compiler}{this is the Haskell compiler}
\item \textbf{GHCi}: \ifger{das ist die interaktive Compiler-Umgebung, ähnlich der ruby shell \emph{irb}}{this an interactive environment of GHC, similar to the interactive ruby shell \emph{irb}}
\item \textbf{The Haskell Platform}: \ifger{eine Kollektion die GHC, GHCi und Standardbibliotheken beinhaltet}{a collection including GHC, GHCi and basic libraries}\footnote{\url{https://www.haskell.org/platform}}
\item \ifger{Haskell IDEs}{haskell IDEs}\footnote{\url{https://wiki.haskell.org/IDEs}}
\end{itemize}
\item \textbf{The Haskell Platform}: \ifger{eine Kollektion die GHC, GHCi und Standardbibliotheken beinhaltet}{a collection including GHC, GHCi and basic libraries}
\end{itemize}
\ifger{Siehe}{Go to}\footnote{\url{https://www.haskell.org/platform}}\\
\ifger{Für Haskell IDEs, siehe}{For haskell IDEs, see}\footnote{\url{https://wiki.haskell.org/IDEs}}

View File

@ -4,7 +4,4 @@
\item \ifger{unendliche Datenstrukturen sind möglich, sowohl rekursive als auch nicht-rekursive}{infinite data structures are now possible (recursive and non-recursive)}
\item \ifger{neue Kontrollstrukturen können sehr leicht durch Definieren von Funktionen erzeugt werden, wir benötigen nicht unbedingt if-then-else}{defining new control structures by just defining a function (since not everything is evaluated... who needs if-then-else anyway?)}
\item \ifger{sehr wichtig für die Programmierung mit Komposition (z.b. Funktionskomposition) und Effizienz}{important for compositional programming and efficiency}
\end{itemizep}
\slidep
\vspace{\baselineskip}
\ifger{Frage:}{Question:} call-by-value? call-by-reference? call-by-need?
\end{itemizep}

View File

@ -13,4 +13,7 @@
\item \ifger{Parallelisierung}{parallelism}
\item \ifger{Denken in Gleichungen und hohes Refactoring-Potenzial}{equational reasoning and refactoring}
\item \ifger{weniger Bugs!}{less bugs!}
\end{itemizep}
\end{itemizep}
\slidep
\vspace{\baselineskip}
\ifger{Frage:}{Question:} call-by-value? call-by-reference? call-by-need?

View File

@ -4,7 +4,6 @@
\item pure
\item lazy
\item \ifger{statisch typisiert (und typsicher)}{statically typed (and truly type-safe)}
\item general purpose language
\item \ifger{sogar}{even} garbage collected
\item \ifger{die beste imperative Programmiersprache der Welt (was??)}{the world's finest imperative language (what??)}
\end{itemize}

View File

@ -3,5 +3,4 @@
\item \ifger{wie schreibe ich Haskell Funktionen?}{how you write haskell functions?}
\item \ifger{wie gehe ich mit Listen und Tuplen um?}{how you handle lists and pairs?}
\item \ifger{wie funktioniert pattern matching?}{how you do pattern matching?}
\item \ifger{wie man seine eigenen Datentypen definiert}{how you create your own data types}
\end{itemize}

View File

@ -11,7 +11,6 @@
\slide{./content/VL2_polymorphism1.tex}
\slide{./content/VL2_polymorphism2.tex}[ (cnt.)]
\slide{./content/VL2_polymorphism3.tex}[ (cnt.)]
\section{\ifger{Andere Arten der Funktionsdefinition}{More ways to define functions}}
@ -54,7 +53,6 @@
\subsection{\ifger{Schlussfolgerung}{Conclusion}}
\slide{./content/VL2_currying5.tex}
\slide{./content/VL2_currying5.1.tex}[ (cnt.)]
\subsection{Partial application}
\slide{./content/VL2_currying6.tex}

View File

@ -2,7 +2,7 @@
\vspace{\baselineskip}
\\
\ifger{Aus der Mathematik wissen wir bereits, dass:}{From maths we already know that:}\\
$(f \circ g)(x) = f(g(x))$
$(g \circ f)(x) = g(f(x))$
\vspace{\baselineskip}
\\
\pause
@ -14,7 +14,7 @@ composedFunction x = (f . g) x
-- is evaluated first
composedFunction x = f . g $ x
-- and same again, remember that 'g x ='
-- and same again, remember that 'f x ='
-- is just syntax sugar
-- omitting the x here is also called eta reduction
composedFunction = f . g

View File

@ -10,4 +10,4 @@ addInt x y = x + y
addInt :: (Int, Int) -> Int
addInt (x, y) = x + y
\end{haskellcode}
\ifger{was im Grunde der Sache sogar recht nahe kommt. Denn die Beziehung beider Schreibweisen ist eigentlich schon \textbf{Currying}.}{which is actually pretty close. Because the connection between both syntax is exactly that: \textbf{currying}.}
\ifger{was im Grunde der Sache sogar recht nahe kommt.}{which is actually pretty close.}

View File

@ -3,21 +3,16 @@ $f(x, y) = y / x$
\vspace{\baselineskip}
\\
\pause
\ifger{Um diese Funktion für $x = 2$ und $y = 3$ zu berechnen würden wir normalerweise einfach einsetzen:}{In order to evaluate the function for $x = 2$ and $y = 3$ we would usually just do:}\\
$f(2, 3) = 3 / 2$
\ifger{Um diese Funktion für $x = 2$ und $y = 3$ zu berechnen würden wir einfach einsetzen:}{In order to evaluate the function for $x = 2$ and $y = 3$ we would do:}\\
$f(2, 3) = 2 / 3$\\
\ifger{und fertig sein.}{and be done.}
\vspace{\baselineskip}
\\
\pause
\ifger{Allerdings, wie wäre es wenn wir daraus eine Funktion mit nur dem Argument $x$ formulieren:}{However, how about we first make a function that only has $x$ as an argument:}\\
$h(x) = y \mapsto f(x, y)$\\
\ifger{Dies ist bereits die curried Variante von $f$!}{This is a curried version of $f$!}
\ifger{Allerdings, wie wäre es wenn wir nur für $x$ einsetzen und dadurch eine neue Funktion definieren. Da $x$ weg ist, können wir schreiben:}{However, how about we just put in $x$ first and make a new function. Since $x$ is gone, we can write:}\\
$g(y) = f(2, y) = y / 2$
\vspace{\baselineskip}
\\
\pause
\ifger{Wenn wir jetzt für $x = 2$ einsetzen, können wir eine weitere Funktion definieren:}{If we fix $x = 2$ we can make another function:}\\
$g(y) = h(2) = y \mapsto f(2, y) = y / 2$
\vspace{\baselineskip}
\\
\pause
\ifger{Und erst im letzten Schritt lösen wir die Gleichung indem wir $y$ in $g(y)$ einsetzen:}{And in the last step we solve the function $g(y)$:}\\
\ifger{Und erst in einem zweiten Schritt lösen wir die Gleichung indem wir $y$ in $g(y)$ einsetzen:}{And in a second step we solve the function $g(y)$:}\\
$g(3) = f (2, 3) = 3 / 2$

View File

@ -1,5 +1,7 @@
\ifger{Wir können uns das ganze auch geometrisch vorstellen:}{You can also imagine this geometrically:}\\
$z = f(x, y)$ \ifger{hat eine 2-dimensionale Definitionsmenge}{has a 2-dimensional set of definitions}. \ifger{Wenn wir für die Variable $y$ einsetzen legen wir quasi die Schnittebene fest und bekommen als Funktion die Schnittkurve (1-dimensionale Definitionsmenge). Die Schnittkurve $s(x) = f(x, y)|_{y = 1}$ können wir jetzt durch einsetzen von $x$ auswerten, um $z$ zu berechnen.}{If we fix the variable $y$, then we've defined the intersecting plane and get a function for the intersection curve $s(x) = f(x, y)|_{y = 1}$ (1-dimensional set of definitions). If we fix $x$ here, we'll get our $z$.}\\
\includegraphics*[width=0.5\textwidth]{./images/Grafico_3d_x2+xy+y2.png}
\vspace{\baselineskip}\\
$z = f(x, y)$ \ifger{ist}{is} 3-dimensional. \ifger{Wenn wir für die Variable $x$ einsetzen bekommen wir im Grunde eine 2-dimensionale Funktion (die Schnittebene). Wenn wir dann für $y$ einsetzen, bekommen wir den eigentlich Punkt $z$.}{If you fix the variable $x$ you'll make things 2-dimensional (the intersecting plane). If you then fix $y$ you'll get an actual point $z$.}
\vspace{\baselineskip}
\\
\includegraphics*[scale=0.4]{./images/Grafico_3d_x2+xy+y2.png}
\\
\ifger{Für jeden dieser Schritte können wir eine echte neue Funktion definieren. Das funktioniert mit einer beliebigen Anzahl von Dimensionen/Argumenten.}{For every of these steps we can define a real new function. This scales up to any number of dimensions/arguments.}

View File

@ -1,16 +0,0 @@
\ifger{Also, wenn wir in Haskell scheinbar mehrere Argumente einer Funktion übergeben, steckt immer Currying dahinter. Es erzeugt eine Reihe von Zwischenfunktionen (oder anonyme Funktionen) mit jeweils einem Argument und evaluiert diese dann schrittweise.}{So, if we seemingly pass multiple arguments into a function, then there is always currying behind it. It creates those intermediate/anonymous functions, all with one argument only, and then evaluates them stepwise.}
\begin{haskellcode}
-- this is more or less just syntax sugar...
f x y z = x + y + z
-- ...for this
f = \x -> (\y -> (\z -> x + y + z)) -- right-associative
\end{haskellcode}
\ifger{Frage: was passiert, wenn wir nur $x = 3$ übergeben?}{Question: what happens if we just pass $x = 3$?}
\vspace{\baselineskip}
\\
\pause
\ifger{Wieso nicht das?}{Why not this?}
\begin{haskellcode}
f = \x -> x + (\y -> y + (\z -> z)) -- no!
\end{haskellcode}

View File

@ -8,7 +8,7 @@ $f' : A_1 \mapsto (A_2 \mapsto (\ ...\ (A_n \mapsto B)))$
\vspace{\baselineskip}
\\
\pause
\ifger{Die Klammern hier sind äußerst wichtig! Currying ist \emph{rechts}-assoziativ, d.h. die folgenden 2 Typsignaturen sind äquivalent:}{The braces are \textbf{very} important! It means currying is \emph{right}-associative and these these two signatures are equivalent:}
\ifger{Die Klammern hier sind äußerst wichtig! Currying ist \emph{rechts}-assoziativ, d.h. die folgenden 2 Typsignaturen in Haskell sind äquivalent:}{Did you just notice the braces? They are \textbf{very} important! So, currying is \emph{right}-associative which means that these two signatures are equivalent:}
\begin{haskellcode}
f :: Int -> Int -> Int
f :: Int -> (Int -> Int)
@ -16,6 +16,4 @@ f :: Int -> (Int -> Int)
-- but this is NOT the same
f :: (Int -> Int) -> Int
\end{haskellcode}
\ifger{Auf der anderen Seite ist Funktionsanwendung \emph{links}-assoziativ, d.h.}{On the other hand function application is \emph{left}-associative, so} \hinline{f 3 2} \ifger{ist nur die Kurzform für}{is just a shorthand of} \hinline{(f 3) 2}.
\vspace{\baselineskip}
\\
\ifger{Auf der anderen Seite ist Funktionsanwendung \emph{links}-assoziativ, d.h.}{On the other hand function application is \emph{left}-associative, so} \hinline{f 3 2} \ifger{ist nur die Kurzform für}{is just a shorthand of} \hinline{(f 3) 2}. \ifger{Macht Sinn?}{Makes sense?}

View File

@ -3,14 +3,17 @@
\begin{haskellcode}
addInt :: Int -> Int -> Int
addInt x y = x + y
-- which is equivalent to this as we already know
addInt = \x -> (\y -> x + y)
addTwo :: Int -> Int
addTwo = addInt 2
\end{haskellcode}
\ifger{Wir haben \hinline{addInt} ein Argument übergeben, also ist die Arität (im Beispiel vorher Dimension) einer weniger und damit ist noch ein Argument notwendig um den endgültigen Wert zu bekommen.
\vspace{\baselineskip}\\
Oder in anderen Worten: wir haben der Zwischenfunktion, die Currying für uns erstellt hat, lediglich den Namen \hinline{addTwo} gegeben.}{We gave \hinline{addInt} one argument, so the arity (we called it dimension in the gemoetrical example) is one less, but there is still one argument left we can pass in.
\vspace{\baselineskip}\\
Or in other words: we just gave the intermediate function that currying created for us the name \hinline{addTwo}. That's it.}\vspace{\baselineskip}\\
\ifger{Warum haben wir nicht \hinline{addTwo x = ...} geschrieben? Wieso sollten wir? Wir haben \hinline{addInt} ein Argument übergeben, also ist die Arität (im Beispiel vorher Dimension) einer weniger und damit ist noch ein Argument notwendig um den endgültigen Wert zu bekommen.}{You probably noticed that we did not write \hinline{addTwo x = ...}, but why would we? We gave \hinline{addInt} one argument, so the arity (we called it dimension in the gemoetrical example) is one less, but there is still one parameter left we can pass in.}
\pause
\ifger{Der Grund warum wir \hinline{x} auslassen können ist, dass}{The reason we can omit the \hinline{x} here is that}
\begin{haskellcode}
f x y z = ...
\end{haskellcode}
\ifger{nur syntax sugar ist für}{is just syntax sugar for}
\begin{haskellcode}
f = \x -> (\y -> (\z -> ... )) -- right-associative, ofc
\end{haskellcode}

View File

@ -1,4 +1,4 @@
\ifger{Wie am Anfang dieses Kapitels bereits gesagt sind diese beiden Funktionen sehr ähnlich:}{As said in the beginning of this section, these two look pretty similar:}
\ifger{Wie am Anfang dieses Kapitels bereits gesagts sind diese beiden Funktionen sehr ähnlich:}{As said in the beginning of this section, these two look pretty similar:}
\begin{haskellcode}
f :: Int -> Int -> Int

View File

@ -6,7 +6,7 @@ filter :: (a -> Bool) -> [a] -> [a]
\pause
\begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a]
filter f [] = []
filter f [] = []
filter f (x:xs)
| f x = x : filter f xs
| otherwise = filter f xs

View File

@ -6,20 +6,20 @@ sum :: [Int] -> Int
\pause
\begin{haskellcode}
sum :: [Int] -> Int
sum [] = 0
sum [] = 0
sum (x:xs) = x + sum xs
\end{haskellcode}
\pause
\ifger{Oder das Produkt:}{Or the product:}
\begin{haskellcode}
prod :: [Int] -> Int
prod [] = 1
prod [] = 1
prod (x:xs) = x * prod xs
\end{haskellcode}
\pause
\ifger{Oder die Länge:}{Or the length:}
\begin{haskellcode}
length :: [a] -> Int
length [] = 0
length [] = 0
length (x:xs) = 1 + length xs
\end{haskellcode}

View File

@ -1,14 +1,14 @@
\ifger{Um es kurz zu machen, die abstrakte Lösung ist:}{To cut the story short, the abstract solution looks like this:}
\begin{haskellcode}
fold :: (a -> b -> b) -> b -> [a] -> b
fold f z [] = z
fold f z (x:xs) = x `f` (fold f z xs)
fold :: b -> (a -> b -> b) -> [a] -> b
fold z f [] = z
fold z f (x:xs) = x `f` (fold z f xs)
\end{haskellcode}
Whoa! What's going on here?\\
\ifger{Schauen wir genauer hin...}{Let's see...}
\begin{itemizep}
\item \hinline{f} \ifger{ist unsere Funktion}{is our function} (\ifger{z.b.}{e.g.} \hinline{(*)} \ifger{oder}{or} \hinline{(+)})
\item \hinline{z} \ifger{ist was die Funktion zurückgibt, wenn die Liste leer ist}{is what we return if the list is empty}
\item \hinline{f} \ifger{ist unsere Funktion}{is our function} (\ifger{z.b.}{e.g.} \hinline{(*)} \ifger{oder}{or} \hinline{(+)})
\item \ifger{das letzte Argument ist die eigentliche Liste, auf der wir arbeiten}{and the last remaining argument is the actual list we are working on}
\end{itemizep}
\slidep

View File

@ -2,13 +2,13 @@
\pause
\begin{haskellcode}
sum :: [Int] -> Int
sum xs = fold (\x y -> x + y) 0 xs
sum xs = fold 0 (\x y -> x + y) xs
-- a Haskeller would write
sum = fold (+) 0
sum = fold 0 (+)
prod :: [Int] -> Int
prod xs = fold (\x y -> x * y) 1 xs
prod xs = fold 1 (\x y -> x * y) xs
length :: [a] -> Int
length xs = fold (\x y -> 1 + y) 0 xs
length xs = fold 0 (\x y -> 1 + y) xs
\end{haskellcode}

View File

@ -1,7 +1,7 @@
\ifger{Lösung:}{Solution:}
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo [] = []
addTwo [] = []
addTwo (x:xs) = (x + 2) : addTwo xs
\end{haskellcode}
\pause
@ -9,14 +9,14 @@ addTwo (x:xs) = (x + 2) : addTwo xs
\pause
\begin{haskellcode}
square :: [Int] -> [Int]
square [] = []
square [] = []
square (x:xs) = (x * x) : square xs
\end{haskellcode}
\pause
\ifger{Jetzt wollen wir den Betrag jedes Elements:}{Now we want the absolute of every element:}
\begin{haskellcode}
absList :: [Int] -> [Int]
absList [] = []
absList [] = []
absList (x:xs) = (abs x) : absList xs
\end{haskellcode}
\pause

View File

@ -3,7 +3,7 @@
f :: Int -> Int
f x = x + 1
\end{haskellcode}
\ifger{Aber stellen wir uns vor, dass wir eine Hilfsfunktion benötigen, die sehr spezifisch ist und eigentlich zur aktuellen Funktion gehört. In C würden wir diese vermutlich top-level deklarieren und \cinline{static} machen.}{But now imagine we need a helper function which is very specific to the current function. In C we would have to define this new helper function at top-level and would probably make it \cinline{static}.}
\ifger{Aber stellen wir uns vor, dass wir einige Hilfsfunktionen benötigen, die sehr spezifisch ist und eigentlich zur aktuellen Funktion gehört. In C würden wir diese vermutlich top-level deklarieren und \cinline{static} machen.}{But now imagine we need a helper function which is very specific to the current function. In C we would have to define this new helper function at top-level and would probably make it \cinline{static}.}
\pause
\vspace{\baselineskip}
\\

View File

@ -2,19 +2,4 @@
\vspace{\baselineskip}
\\
\pause
\ifger{Noch besser sogar! Haskell erlaubt standardmäßig Polymorphie, ohne komplizierte APIs oder Spracherweiterungen.}{Even better! Haskell supports polymorphism for both data types and functions, out of the box without any language extensions.}\\
\ifger{Wir beginnen mit einem polymorphen Datentyp:}{Let's start with a polymorphic data type:}
\begin{haskellcode}
data List t = Empty | Cons t (List t)
\end{haskellcode}
\ifger{Wir haben soeben unsere eigene singly-linked Liste implementiert. Für jeden Typ! Ein paar Beispiele:}{So we just implemented our own singly-linked List. For any type! Let's use it:}
\pause
\begin{haskellcode}
intList :: List Int
intList = Cons 3 (Cons 5 (Cons 2 Empty))
charList :: List Char
charList = Cons 'x' (Cons 'y' (Cons 'z' Empty))
-- whatever you can imagine goes here
\end{haskellcode}
\ifger{Noch besser sogar! Haskell erlaubt standardmäßig Polymorphie, ohne komplizierte APIs oder Spracherweiterungen.}{Even better! Haskell supports polymorphism for both data types and functions, out of the box without any language extensions.}

View File

@ -1,12 +1,19 @@
\ifger{Und jetzt können wir sie nutzen:}{And now we are going to write functions to use it:}
\ifger{Beginnen wir mit einer polymorphen Funktion, die wir bereits kennen:}{Let's start with a polymorphic function that you already know:}
\begin{haskellcode}
isListEmpty :: List t -> Bool
isListEmpty Emtpy = True
isListEmpty x = False
head :: [a] -> a
\end{haskellcode}
\pause
\ifger{Also, }{So} \hinline{head} \ifger{nimmt eine Liste irgendeines (unbekannten) Typs und gibt uns ein einziges Elements dieser Liste zurück, mit \emph{exakt} demselben Typ.}{takes a list of any type and returns an element which must have the \emph{exact same} type of that list.}
\vspace{\baselineskip}
\\
\pause
\ifger{Wir können sogar Funktionen schreiben wie:}{We can also have:}
\begin{haskellcode}
f :: a -> b
\end{haskellcode}
\ifger{D.h. was auch immer diese Funktion macht, sie bekommt etwas von einem Typ rein und gibt etwas von einem anderen Typ aus. \hinline{a} und \hinline{b} könnten vom selben Typ sein, müssen aber nicht! D.h. Funktionen dieser Art geben uns häufig mehr Freiheit. Mehr können wir über diese Funktion nicht sagen.}{So, whatever the function does... it gets something of one type and returns something of another type. \hinline{b} \emph{could} be the same type as \hinline{a} here, but it doesn't need to, so functions of this type often give us more freedom! That's all we know about this function.}
\pause
\ifger{D.h. was auch immer diese Funktion macht, sie bekommt etwas von einem Typ rein und gibt etwas von einem anderen Typ aus. \hinline{a} und \hinline{b} könnten vom selben Typ sein, müssen aber nicht! D.h. Funktionen dieser Art geben uns häufig mehr Freiheit. Mehr können wir über diese Funktion nicht sagen.}{So, whatever the function does... it gets something of one type and returns something of another type. \hinline{b} \emph{could} be the same type as \hinline{a} here, but it doesn't need to, so functions of this type often give us more freedom! That's all we know about this function.}
\vspace{\baselineskip}
\\
\pause
\ifger{Hinweis: wir müssen nicht die Buchstaben \hinline{a} und \hinline{b} nehmen. Sie werden nur häufig für generische Datentypen benutzt.}{Note: you don't have to use \hinline{a} or \hinline{b} here. These letters are just commonly used for generic types.}

View File

@ -1,8 +0,0 @@
\ifger{Erinnern wir uns an die Funktion \hinline{head}. Wir können auf jeder Art von Liste mit ihr operieren. Die Typsignatur:}{Similarly, remember the function \hinline{head} which gives us the first element of a list? The type signature actually looks like this:}
\begin{haskellcode}
head :: [a] -> a
\end{haskellcode}
\ifger{Macht Sinn?}{Makes sense?}
\vspace{\baselineskip}\\
\pause
\ifger{Frage: könnte \hinline{a} eine Funktion sein?}{Question: could \hinline{a} be a function?}

View File

@ -1,6 +1,6 @@
\begin{itemize}
\item \ifger{was ist der Unterschied zwischen}{what is the difference between} \hinline{let} \ifger{und}{and} \hinline{where}?
\item \ifger{was ist der Unterschied zwischen}{what is the difference between} \hinline{foldr} \ifger{und}{and} \hinline{foldl}? \ifger{Welches davon ist tail bzw. head recursive?}{Which one is tail and which one head recursive?}
\item \ifger{was ist der Unterschied zwischen}{what is the difference between} \hinline{foldr} \ifger{und}{and} \hinline{foldl}?
\item \ifger{was ist der Unterschied zwischen expliziter und impliziter Rekursion? Beispiele?}{what is the difference between explicit and implicit recursion? Give examples}
\item \ifger{wie viele Argumente hat eine Haskell Funktion (streng genommen)?}{how many arguments does a haskell function have (strictly speaking)?}
\item \ifger{Sind diese Typsignaturen technisch äquivalent?}{Are these type signatures technically equivalent?}

View File

@ -2,5 +2,4 @@
\item \ifger{Was ist Haskell? Was sind die 3 fundamentalen Konzepte hinter Haskell?}{What is haskell? What are the 3 fundamental concepts behind it?}
\item \ifger{Wie funktioniert pattern matching?}{How do you do pattern matching?}
\item \ifger{Was ist der Unterschied zwischen einer Liste und einem Tuple? Wie erzeugt man sie?}{What is the difference between lists and tuples? How do you construct them?}
\item \ifger{Wie definieren wir unsere eigenen Datentypen?}{How do you define your own data types?}
\end{itemize}

View File

@ -1,5 +1,5 @@
\begin{itemize}
\item \ifger{wie man polymorphe Funktionen und Datentypen schreibt}{how to write polymorphic data types and functions}
\item \ifger{wie man polymorphe Funktionen schreibt}{how to write polymorphic functions}
\item \ifger{wie man \emph{inline} Funktionen schreibt}{how you inline functions}
\item \ifger{was Currying ist und wieso wir es in Haskell benötigen}{what currying is and why we need it in haskell}
\item \ifger{wie man Funktionen verkettet}{how you compose functions}