Compare commits

...

40 Commits

Author SHA1 Message Date
Julian Ospald
1820b61f40
Add newline 2015-05-16 13:22:48 +02:00
Julian Ospald
ec81776d50
Improve questions slide 2015-05-16 13:21:17 +02:00
Julian Ospald
87b8d91fe2
Improve haskell summary slide 2015-05-12 19:55:13 +02:00
Julian Ospald
049802ff92
Improve fold slides 2015-05-02 17:51:56 +02:00
Julian Ospald
a16fa8e5ae
Improve currying slides further 2015-05-02 13:59:58 +02:00
Julian Ospald
e21d6aaf3f
Improve currying slides 2015-05-02 13:45:22 +02:00
Julian Ospald
952e477666
Improve currying slide 2015-05-02 12:51:43 +02:00
Julian Ospald
1f33467433
Fix/improve currying slides 2015-05-01 20:59:59 +02:00
Julian Ospald
8ee83bd02b
Fix spelling 2015-05-01 16:59:39 +02:00
Julian Ospald
5fefc209f6
Simplify function composition slide 2015-05-01 16:42:18 +02:00
Julian Ospald
a5034b1812
Improve code prettiness 2015-05-01 16:42:06 +02:00
Julian Ospald
3feb500826
Improve and restructure currying slides 2015-05-01 16:41:50 +02:00
Julian Ospald
f45e3b192f
Improve pattern matching slide 2015-05-01 16:41:24 +02:00
Julian Ospald
4b7eb36c5e
Improve toolchain slide 2015-04-29 22:23:25 +02:00
Julian Ospald
7ea86009d9
Move call-by-need question zo laziness 2015-04-29 22:14:13 +02:00
Julian Ospald
4f138f5995
Add questions for pairs 2015-04-29 22:14:07 +02:00
Julian Ospald
3f9c4bed57
Add pause 2015-04-29 22:14:01 +02:00
Julian Ospald
8a695659ae
Add more arithmetic examples 2015-04-29 22:13:55 +02:00
Julian Ospald
4c0c549d85
Add question 2015-04-28 12:58:07 +02:00
Julian Ospald
eaf2a52956
Improve pitfalls slide
Let's be honest, laziness can be a pitfall.
2015-04-27 15:26:39 +02:00
Julian Ospald
fc718cdfd0
Fix spelling 2015-04-27 15:26:33 +02:00
Julian Ospald
b09e11aef9
Improve polymorphism slides
# Conflicts:
#	VL2/content/VL2_polymorphism2.tex
2015-04-26 13:42:55 +02:00
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
88 changed files with 456 additions and 534 deletions

View File

@ -16,7 +16,7 @@ VL2:
clean: clean:
$(MAKE) -C VL1 clean $(MAKE) -C VL1 clean
$(MAKE) -C VL2 clean $(MAKE) -C VL2 clean
$(RM) VL1.pdf VL2.pdf VL1/VL1_handout.pdf VL2/VL2_handout.pdf $(RM) VL1.pdf VL2.pdf VL1_handout.pdf VL2_handout.pdf
.PHONY: all clean VL1 VL2 .PHONY: all clean VL1 VL2

View File

@ -5,15 +5,15 @@
% title page information % title page information
\author{Julian Ospald} \author{Julian Ospald}
\institute{FH Bielefeld} \institute{FH Bielefeld}
\title{Haskell: introduction} \title{Haskell: \ifger{Einführung}{introduction}}
\begin{document} \begin{document}
\frame{\titlepage} \frame{\titlepage}
\begin{frame} \begin{frame}
\frametitle{Table of Contents} \frametitle{\ifger{Inhaltsverzeichnis}{Table of Contents}}
\tableofcontents[hidesubsections=true] \tableofcontents[hidesubsections=true,subsubsectionstyle=hide]
\end{frame} \end{frame}
\input{./VL1_document_structure.tex} \input{./VL1_document_structure.tex}

View File

@ -1,76 +1,82 @@
\section{Why haskell?} \section{\ifger{Wieso haskell?}{Why haskell?}}
\slidetoc \slidetoc
\slide{./content/VL1_why_haskell1.tex} \slide{./content/VL1_why_haskell1.tex}
\subsection{Comparsion C and C++} \subsection{\ifger{Vergleich mit C und C++}{Comparsion C and C++}}
\slide{./content/VL1_why_haskell2.tex} \slide{./content/VL1_why_haskell2.tex}
\slide{./content/VL1_why_haskell3.tex}[ (cnt.)] \slide{./content/VL1_why_haskell3.tex}[ (cnt.)]
\subsection{Comparsion Java} \subsection{\ifger{Vergleich mit Java}{Comparsion Java}}
\slide{./content/VL1_why_haskell4.tex} \slide{./content/VL1_why_haskell4.tex}
\slide{./content/VL1_why_haskell5.tex}[ (cnt.)] \slide{./content/VL1_why_haskell5.tex}[ (cnt.)]
\section{What is haskell?} \section{\ifger{Was ist Haskell?}{What is haskell?}}
\slidetoc \slidetoc
\slide{./content/VL1_what_is_haskell.tex} \slide{./content/VL1_what_is_haskell.tex}
\subsection{What does functional mean?} \subsection{\ifger{Was bedeutet funktional?}{What does functional mean?}}
\slide{./content/VL1_what_does_functional_mean1.tex} \slide{./content/VL1_what_does_functional_mean1.tex}
\slide{./content/VL1_what_does_functional_mean2.tex} \slide{./content/VL1_what_does_functional_mean2.tex}
\subsection{What does pure mean?} \subsection{\ifger{Was bedeutet pure?}{What does pure mean?}}
\slide{./content/VL1_what_does_pure_mean.tex} \slide{./content/VL1_what_does_pure_mean.tex}
\subsection{What does lazy mean?} \subsection{\ifger{Was bedeutet lazy?}{What does lazy mean?}}
\slide{./content/VL1_what_does_lazy_mean.tex} \slide{./content/VL1_what_does_lazy_mean.tex}
\subsection{What does statically typed mean?} \subsection{\ifger{Was bedeutet statisch typisiert?}{What does statically typed mean?}}
\slide{./content/VL1_what_does_statically_typed_mean.tex} \slide{./content/VL1_what_does_statically_typed_mean.tex}
\subsection{What is haskell, Summary} \subsection{\ifger{Zusammenfassung: Was ist Haskell?}{Summary: what is haskell?}}
\slide{./content/VL1_what_is_haskell_summary.tex} \slide{./content/VL1_what_is_haskell_summary.tex}
\section{How to think haskell?} \section{\ifger{In Haskell denken}{How to think haskell?}}
\slide{./content/VL1_how_to_think_haskell.tex} \slide{./content/VL1_how_to_think_haskell.tex}
\section{How to write haskell?} \section{\ifger{Haskell schreiben}{How to write haskell?}}
\slidetoc \slidetoc
\subsection{Declarations} \subsection{\ifger{Deklarationen}{Declarations}}
\slide{./content/VL1_declarations.tex} \slide{./content/VL1_declarations.tex}
\subsection{Arithmetic and co.} \subsection{\ifger{Arithmetic und co.}{Arithmetic and co.}}
\slide{./content/VL1_arithmetic_and_co.tex} \slide{./content/VL1_arithmetic_and_co.tex}
\subsection{Functions and control structures} \subsection{\ifger{Funktionen und Kontrollstrukturen}{Functions and control structures}}
\slidetoc
\slide{./content/VL1_functions_and_control_structures1.tex} \slide{./content/VL1_functions_and_control_structures1.tex}
\subsubsection{Pattern matching} \subsubsection{Pattern matching}
\slide{./content/VL1_functions_and_control_structures2.tex} \slide{./content/VL1_pattern_matching.tex}
\subsubsection{Guards and recursion} \subsubsection{Case... of}
\slide{./content/VL1_functions_and_control_structures3.tex} \slide{./content/VL1_case_of.tex}
\subsection{Lists} \subsubsection{\ifger{Guards und Rekursion}{Guards and recursion}}
\slide{./content/VL1_guards_and_recursion.tex}
\subsection{\ifger{Listen}{Lists}}
\slide{./content/VL1_lists1.tex} \slide{./content/VL1_lists1.tex}
\slide{./content/VL1_lists2.tex}[ (cnt.)] \slide{./content/VL1_lists2.tex}[ (cnt.)]
@ -80,35 +86,19 @@
\slide{./content/VL1_lists4.tex} \slide{./content/VL1_lists4.tex}
\subsection{Pairs} \subsection{\ifger{Tuple/Paare}{Pairs}}
\slide{./content/VL1_pairs.tex} \slide{./content/VL1_pairs.tex}
\subsection{Algebraic Data Types}
\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 generalized}
\slide{./content/VL1_ADT7.tex}
\section{Résumé} \section{Résumé}
\slidetoc \slidetoc
\subsection{Questions so far?} \subsection{\ifger{Fragen soweit?}{Questions so far?}}
\slide{./content/VL1_questions_from_you.tex} \slide{./content/VL1_questions_from_you.tex}
\subsection{Common misconceptions} \subsection{\ifger{Häufige Vorurteile}{Common misconceptions}}
\slide{./content/VL1_common_misconceptions.tex} \slide{./content/VL1_common_misconceptions.tex}
@ -116,7 +106,7 @@
\slide{./content/VL1_pitfalls.tex} \slide{./content/VL1_pitfalls.tex}
\subsection{Difficulties} \subsection{\ifger{Schwierigkeiten}{Difficulties}}
\slide{./content/VL1_difficulties1.tex} \slide{./content/VL1_difficulties1.tex}
\slide{./content/VL1_difficulties2.tex}[ (cnt.)] \slide{./content/VL1_difficulties2.tex}[ (cnt.)]
@ -125,19 +115,19 @@
\slide{./content/VL1_toolchain.tex} \slide{./content/VL1_toolchain.tex}
\section{Reflection} \section{\ifger{Reflexion}{Reflection}}
\slidetoc \slidetoc
\subsection{What you should know} \subsection{\ifger{Was Sie wissen sollten}{What you should know}}
\slide{./content/VL1_what_you_should_know.tex} \slide{./content/VL1_what_you_should_know.tex}
\subsection{Questions for you} \subsection{\ifger{Fragen an Sie}{Questions for you}}
\slide{./content/VL1_questions_for_you.tex} \slide{./content/VL1_questions_for_you.tex}
\section{References} \section{\ifger{Referenzen}{References}}
\slidetoc \slidetoc
@ -145,6 +135,6 @@
\slide{../common/content/VL_links.tex} \slide{../common/content/VL_links.tex}
\subsection{Sources} \subsection{\ifger{Quellen}{Sources}}
\slide{../common/content/VL_sources.tex} \slide{../common/content/VL_sources.tex}

View File

@ -6,7 +6,7 @@
% title page information % title page information
\author{Julian Ospald} \author{Julian Ospald}
\title{Haskell: introduction} \title{Haskell: \ifger{Einführung}{introduction}}
\maketitle \maketitle

View File

@ -1,20 +0,0 @@
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}
This declares the new data type \hinline{WeekDay} with 7 \emph{constructors}. That means \hinline{Monday}, \hinline{Tuesday} etc. are all values of the type \hinline{WeekDay}.
\pause
\\
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 @@
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 @@
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
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 @@
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
And pattern match on it as well:
\begin{haskellcode}
addIntToList :: MaybeInt -> [Int]
addIntToList (NoError x) = [x]
addIntToList (Error str) = []
\end{haskellcode}
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 @@
Let's define something more complex. How about a tree?
\pause
\begin{haskellcode}
data Tree = Leaf Char
| Node Tree Int Tree
\end{haskellcode}
Uh... that looks mean. Let's examine this.\\
\pause
We have:
\begin{itemizep}
\item defined a data type \hinline{Tree}
\item a constructor \hinline{Leaf} of type \hinline{Tree} with one arguments of type \hinline{Char}
\item 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
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}.\\
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 @@
Let's build our tree:
\begin{haskellcode}
tree :: Tree
tree = Node
(Leaf 'x')
1
(Node
(Leaf 'y')
2
(Leaf 'z')
)
\end{haskellcode}
See board...

View File

@ -1,7 +0,0 @@
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 arguments. E.g.:
\begin{haskellcode}
data AlgDataType = Constr1 Type11 Type12
| Constr2 Type21
| Constr3 Type31 Type32 Type33
| Constr4
\end{haskellcode}

View File

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

View File

@ -0,0 +1,9 @@
\ifger{Wir können auch auf dem Ergebnis eines Ausdruckes pattern matchen, nicht nur auf Eingabeargumente. Dafür schreiben wir:}{We can also pattern match on the result of a real expression, not just the input. For that, we write:}
\begin{haskellcode}
f :: Int -> Bool
f x = case x - 2 of
2 -> True
5 -> True
y -> False
\end{haskellcode}
\ifger{Das erlaubt uns etwas mächtigeres pattern matching}{This allows more powerful pattern matching}.

View File

@ -1,7 +1,7 @@
Now that we know the basics, let's clear up some common misconceptions about haskell. \ifger{Jetzt, da wir die Grundlagen kennen, sollten wir ein paar häufige Missverständnisse ausräumen:}{Now that we know the basics, let's clear up some common misconceptions about haskell.}
\begin{itemizep} \begin{itemizep}
\item haskell is only a language for university professors \item \ifger{Haskell ist eine Sprache nur für Universitätsprofessoren}{haskell is only a language for university professors}
\item haskell is not used in real world, see \url{https://wiki.haskell.org/Haskell_in_industry} \item \ifger{Haskell wird nicht in der Industrie verwendet, siehe}{haskell is not used in real world, see \url{https://wiki.haskell.org/Haskell_in_industry}}
\begin{itemize} \begin{itemize}
\item Microsoft \item Microsoft
\item NVIDIA \item NVIDIA
@ -10,11 +10,11 @@ Now that we know the basics, let's clear up some common misconceptions about has
\item Intel \item Intel
\item AT\Q{&}T \item AT\Q{&}T
\end{itemize} \end{itemize}
\item you cannot model states in haskell \item \ifger{man kann keine Zustände in Haskell modellieren}{you cannot model states in haskell}
\item you cannot write larger programs in haskell \item \ifger{man kann keine komplexeren Programme in Haskell schreiben}{you cannot write larger programs in haskell}
\item you cannot write useful programs in haskell \item \ifger{man kann keine nützlichen Programme in Haskell schreiben}{you cannot write useful programs in haskell}
\item you cannot implement imperative algorithms \item \ifger{man kann keine imperativen Algorithmen in Haskell implementieren}{you cannot implement imperative algorithms}
\item you cannot do concurrency, cryptography, web development, ... in haskell \item \ifger{man kann keine Nebenläufigkeit, Kryptographie, Webdevelopment, ... in Haskell machen}{you cannot do concurrency, cryptography, web development, ... in haskell}
\end{itemizep} \end{itemizep}
\slidep \slidep
You can! \ifger{Doch, kann man! Vorführung?}{You can! Need proof?}

View File

@ -1,4 +1,4 @@
Let's go! \ifger{Auf!}{Let's go!}
\begin{haskellcode} \begin{haskellcode}
x :: Int x :: Int
x = 3 x = 3

View File

@ -1,9 +1,9 @@
Haskell is very powerful and can be used for pretty much anything. However, there are difficulties in any language. Let's name a few for haskell: \ifger{Haskell ist sehr mächtig und kann für praktisch alles verwendet werden. Trotzdem hat es wie jede Sprache auch einige Härten bzw. Schwierigkeiten:}{Haskell is very powerful and can be used for pretty much anything. However, there are difficulties in any language. Let's name a few for haskell:}
\begin{itemizep} \begin{itemizep}
\item intellectual complexity? New way of thinking? \item \ifger{intellektuelle Komplexität? Neue Art zu Denken?}{intellectual complexity? New way of thinking?}
\item although you rarely need it in haskell, debugging can be difficult at times \item \ifger{obwohl man es selten braucht... debuggen kann unter Umständen schwierig sein}{although you rarely need it in haskell, debugging can be difficult at times}
\item 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{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 no premium-like IDE with every possible feature (yet) \item \ifger{(noch) keine premium-IDE mit allen möglichen features}{no premium-like IDE with every possible feature (yet)}
\item dynamic linking is sort of WIP yet, lots of ABI breakage \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 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 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}
\end{itemizep} \end{itemizep}

View File

@ -1,5 +1,5 @@
\begin{itemizep} \begin{itemizep}
\item some problems that are trivial in imperative languages, can be very difficult to solve in idiomatic haskell and vice versa \item \ifger{einige Probleme die trivial in imperativen Sprachen sind, sind sehr schwierig in idiomatischem Haskell zu lösen und umgekehrt}{some problems that are trivial in imperative languages, can be very difficult to solve in idiomatic haskell and vice versa}
\item practical cryptography is possible, but a difficult topic in haskell, see \url{https://mail.haskell.org/pipermail/haskell-cafe/2015-February/118059.html} \item \ifger{praktische Kryptographie ist möglich, aber ein schwieriges Thema, siehe}{practical cryptography is possible, but a difficult topic in haskell, see}\footnote{\url{https://mail.haskell.org/pipermail/haskell-cafe/2015-February/118059.html}}
\item although haskell is \emph{lazy}, there are a few things that can break laziness, see \url{https://wiki.haskell.org/Maintaining_laziness} \item \ifger{obwohl Haskell \emph{lazy} ist, gibt es ein paar Dinge, die laziness zunichte machen können, siehe auch}{although haskell is \emph{lazy}, there are a few things that can break laziness, see}\footnote{\url{https://wiki.haskell.org/Maintaining_laziness}}
\end{itemizep} \end{itemizep}

View File

@ -1,10 +1,10 @@
Let's make our first function. We want something like the following mathematical function\\ \ifger{Schreiben wir unsere erste Funktion. Wir wollen etwas wie die folgende mathematische Funktion:}{Let's make our first function. We want something like the following mathematical function}\\
$f(x) = x * x$ $f(x) = x * x$
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
How could the haskell code look like? \ifger{Wie könnte der Haskell code aussehen?}{How could the haskell code look like?}
\pause \pause
Almost the same: \ifger{Beinahe genauso:}{Almost the same:}
\begin{haskellcode} \begin{haskellcode}
f x = x * x f x = x * x
\end{haskellcode} \end{haskellcode}
@ -13,9 +13,10 @@ GHCi...
\pause \pause
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
What is a possible type signature for this function? \ifger{Was ist eine mögliche Typsignatur dieser Funktion?}{What is a possible type signature for this function?}
\pause
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int f :: Int -> Int
f x = x * x f x = x * x
\end{haskellcode} \end{haskellcode}
So the function gets an Int and returns an Int. Don't get confused by "\verb|->|". Just think of it as a symbol for separating input and output. \ifger{Also, die Funktion bekommt einen \hinline{Int} als Eingabe und gibt einen \hinline{Int} als Ausgabe zurück. Lasst Euch nicht von}{So the function gets an \hinline{Int} and returns an \hinline{Int}. Don't get confused by} \hinline{->} \ifger{verwirren.}{.} \ifger{Seht es einfach als Symbol zum Trennen von Eingabe und Ausgabe}{Just think of it as a symbol for separating input and output}.

View File

@ -1,13 +0,0 @@
In haskell we often use \textbf{pattern matching}. That means we define a function multiple times, but e.g. for different values of its input arguments. Let's see:
\pause
\begin{haskellcode}
isZero :: Int -> Bool
isZero 0 = True
isZero x = False
\end{haskellcode}
\vspace{\baselineskip}
So if we pass it 0, we get True. If we do not pass 0, we get False and the value we passed gets basically ignored.
\vspace{\baselineskip}
\\
\pause
What might happen if we remove the second or the third line? What is a \textbf{partial function} and a \textbf{total function}?

View File

@ -1,10 +0,0 @@
How about \emph{recursion}? Let's define the modulo of any \emph{Int} to \emph{2}.
\pause
\begin{haskellcode}
mod2 :: Int -> Int
mod2 x
| x - 2 == 0 = 0
| x - 2 < 0 = x
| otherwise = mod2 (x - 2)
\end{haskellcode}
These \verb#|# things above are called \textbf{guards} and are similar to \emph{pattern matching}. They are processed in order. If the condition on the left side of the equation is true, then it returns what stands on the right side of the equation. If it's false, then it processes the next line.\\ \hinline{otherwise} on the last line is just defined as \hinline{True}, to make these constructs easier to read and catch all other cases of input.

View File

@ -0,0 +1,10 @@
\ifger{Wie sieht es mit \emph{Rekursion} aus? Wir wollen den Modulo von einem beliebigen \emph{Int} zu \emph{2} definieren.}{How about \emph{recursion}? Let's define the modulo of any \emph{Int} to \emph{2}.}
\pause
\begin{haskellcode}
mod2 :: Int -> Int
mod2 x
| x - 2 == 0 = 0
| x - 2 < 0 = x
| otherwise = mod2 (x - 2)
\end{haskellcode}
\ifger{Diese}{These} \hinline{|} \ifger{Zeichen nennt man \textbf{guards} und sie sind dem \emph{pattern matching} sehr ähnlich. Sie werden von oben nach unten abgearbeitet. Wenn die Bedingung auf der linken Seite der Gleichung wahr ist, dann gibt die gesamte Funktion das heraus, was auf der rechten Seite der Gleichung steht. Ansonsten wird die nächste Zeile ausprobiert. \hinline{otherwise} in der letzten Zeile ist lediglich \hinline{True}, um dieses Konstrukt lesbarer zu machen und fungiert quasi als allgemeines \emph{else}.}{things above are called \textbf{guards} and are similar to \emph{pattern matching}. They are processed in order. If the condition on the left side of the equation is true, then it returns what stands on the right side of the equation. If it's false, then it processes the next line.\\ \hinline{otherwise} on the last line is just defined as \hinline{True}, to make these constructs easier to read and catch all other cases of input.}

View File

@ -1,18 +1,19 @@
\begin{itemizep} \begin{itemizep}
\item forget about imperative, procedural, OOP; forget about any programming language \item \ifger{vergesst was Ihr über imperative, prozedurale oder OOP basierte Sprachen wisst... am besten vergesst alles, was Ihr über Programmiersprachen wisst}{forget about imperative, procedural, OOP; forget about any programming language}
\item think in types! \item \ifger{denkt in Typen!}{think in types!}
\begin{itemizep} \begin{itemizep}
\item don't be afraid of type errors \item \ifger{keine Angst vor Typfehlern!}{don't be afraid of type errors}
\item let the type-checker do the work for you (does this function do what I think it does?) \item \ifger{lass den type-checker die ganze Arbeit tun (macht diese Funktion auch das, was ich denke?)}{let the type-checker do the work for you (does this function do what I think it does?)}
\item understand functions just by looking at their type signature? \item \ifger{Funktionen nur durch das Lesen ihrer Typsignatur verstehen?}{understand functions just by looking at their type signature?}
\end{itemizep} \end{itemizep}
\item think abstract! \item \ifger{abstrakt denken!}{think abstract!}
\begin{itemizep} \begin{itemizep}
\item don't repeat yourself! \item don't repeat yourself!
\item "develop a solution space, rather than an individual solution" -- Ralf Hinze \item ''develop a solution space, rather than an individual solution'' -- Ralf Hinze
\item "imagine a graph, rather than a single path" -- Ralf Hinze \item ''imagine a graph, rather than a single path'' -- Ralf Hinze
\item "first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones" -- Ralf Hinze \item ''first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones'' -- Ralf Hinze
\end{itemizep} \end{itemizep}
\item solve atomic parts of general problems and combine them into greater solutions \item \ifger{löse atomare Teile eines größeren Problems und kombiniere die Einzellösungen zu größeren Lösungen zusammen}{solve atomic parts of general problems and combine them into greater solutions}
\item don't be afraid of recursion! \item \ifger{keine Angst vor Rekursion!}{don't be afraid of recursion!}
\item \ifger{weniger schreiben, mehr denken!}{write less, think more!}
\end{itemizep} \end{itemizep}

View File

@ -1,12 +1,12 @@
The list is probably the most basic data structure in Haskell. Like the array in C. It is a singly-linked list and is very lazy. The compiler has numerous ways to optimize lists, so don't be afraid to use them, even for huge things. \ifger{Die Liste ist vermutlich der grundlegendste Datentyp in Haskell, ähnlich wie das Array in C. Sie ist singly-linked und lazy. Der Compiler beherrscht viele Tricks, die Liste zu optimieren, deshalb kann man sie auch für komplexere Probleme benutzen.}{The list is probably the most basic data structure in Haskell. Like the array in C. It is a singly-linked list and is very lazy. The compiler has numerous ways to optimize lists, so don't be afraid to use them, even for huge things.}
\pause \pause
We build lists by using either the \hinline{[]} notation: \ifger{Wir erzeugen Listen entweder mit der}{We build lists by using either the} \hinline{[]} \ifger{Notation:}{notation:}
\begin{haskellcode} \begin{haskellcode}
list1 :: [Integer] list1 :: [Integer]
list1 = [1, 2] list1 = [1, 2]
\end{haskellcode} \end{haskellcode}
\pause \pause
or by using the \emph{cons} operator \hinline{(:)} which takes an element and a list and produces a new list with the element prepended to the front. \ifger{oder mit dem}{or by using the} \emph{cons} \ifger{Operator}{operator} \hinline{(:)} \ifger{welcher ein Element nimmt und es an den Anfang einer Liste setzt und somit eine neue Liste erzeugt.}{which takes an element and a list and produces a new list with the element prepended to the front.}
\begin{haskellcode} \begin{haskellcode}
emptyList = [] emptyList = []
@ -16,7 +16,7 @@ list2 = 1 : []
list3 = [1, 2] == 1 : 2 : [] list3 = [1, 2] == 1 : 2 : []
\end{haskellcode} \end{haskellcode}
\pause \pause
How about something more interesting: \ifger{Wie wäre es mit etwas interessanterem:}{How about something more interesting:}
\begin{haskellcode} \begin{haskellcode}
infiniteList = [1..] infiniteList = [1..]
\end{haskellcode} \end{haskellcode}

View File

@ -1,4 +1,4 @@
Let's check on a few very common list operations: \ifger{Ein paar häufig verwendete List-Operationen}{Let's check on a few very common list operations:}
\begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi} \begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi}
> [1, 2] ++ [4, 5] -- append two lists > [1, 2] ++ [4, 5] -- append two lists
> head [1, 2, 3] -- first element > head [1, 2, 3] -- first element
@ -10,7 +10,7 @@ Let's check on a few very common list operations:
> elem 7 [1, 2, 3] -- is there a 7 in the list? > elem 7 [1, 2, 3] -- is there a 7 in the list?
\end{haskellcode*} \end{haskellcode*}
\pause \pause
A String in haskell is just a list of Chars! \ifger{Ein String in Haskell ist einfach nur eine Liste von Chars!}{A String in haskell is just a list of Chars!}
\begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi} \begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi}
> ['a', 'b', 'c'] > ['a', 'b', 'c']
> 'a' : [] > 'a' : []

View File

@ -1,15 +1,15 @@
Again, we can do pattern matching on lists. \ifger{Erneut können wir pattern matching anwenden, auch auf Listen.}{Again, we can do pattern matching on lists.}
\begin{haskellcode} \begin{haskellcode}
listLen :: [Integer] -> Integer listLen :: [Integer] -> Integer
listLen [] = 0 listLen [] = 0
listLen (x:xs) = 1 + listLen xs listLen (x:xs) = 1 + listLen xs
\end{haskellcode} \end{haskellcode}
\pause \pause
We can also nest pattern matching: \ifger{Pattern matching können wir auch schachteln:}{We can also nest pattern matching:}
\begin{haskellcode} \begin{haskellcode}
sumEveryTwo :: [Integer] -> [Integer] sumEveryTwo :: [Integer] -> [Integer]
sumEveryTwo [] = 0 sumEveryTwo [] = 0
sumEveryTwo (x:[]) = [x] sumEveryTwo (x:[]) = [x]
sumEveryTwo (x:(y:zs)) = (x + y) : sumEveryTwo zs sumEveryTwo (x:(y:zs)) = (x + y) : sumEveryTwo zs
\end{haskellcode} \end{haskellcode}
Note that \hinline{(x:(y:zs))} may also be written as \hinline{(x:y:zs)}. \ifger{Hinweis...}{Note that} \hinline{(x:(y:zs))} \ifger{kann man auch als}{may also be written as} \hinline{(x:y:zs)}\ifger{ schreiben.}{.}

View File

@ -1,19 +1,19 @@
Haskell also supports \textbf{list comprehension} which is basically syntactic sugar for what we already know from maths.\\ \ifger{Haskell erlaubt auch}{Haskell also supports} \textbf{list comprehension} \ifger{, was eigentlich nur Syntaxsugar ist und der mathematischen Schreibweise sehr ähnelt.}{which is basically syntactic sugar for what we already know from maths.}\\
Let's define a set that contains the first ten even natural numbers:\\ \ifger{Wir wollen ein Set definieren, das die ersten 10 geraden Zahlen beinhaltet:}{Let's define a set that contains the first ten even natural numbers:}\\
\pause \pause
$S = \{2 \times x\ |\ x \in \mathbb{N},\ x \leq 10\}$ $S = \{2 \times x\ |\ x \in \mathbb{N},\ x \leq 10\}$
\vspace{\baselineskip} \vspace{\baselineskip}
\pause \pause
\\ \\
How does this look in haskell? \ifger{Wie könnte das in Haskell aussehen?}{How does this look in haskell?}
\pause \pause
\begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi} \begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi}
> [ 2 * x | x <- [1..10]] > [ 2 * x | x <- [1..10]]
\end{haskellcode*} \end{haskellcode*}
\pause \pause
Now let's say we want all numbers between 50 and 100 that have the remainder 0 when divided by 12: \ifger{Jetzt wollen wir alle Zahlen zwischen 50 und 100 die als Rest 0 haben, wenn wir sie modulo 12 nehmen:}{Now let's say we want all numbers between 50 and 100 that have the remainder 0 when divided by 12:}
\pause \pause
\begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi} \begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi}
> [x | x <- [50..100], mod x 12 == 0] > [x | x <- [50..100], mod x 12 == 0]
\end{haskellcode*} \end{haskellcode*}
\hinline{x <- [50..100]} is the binding, while \hinline{mod x 12 == 0} is the predicate, separated by a comma. We can have multiple predicates. \hinline{x <- [50..100]} \ifger{ist das Binding, während}{is the binding, while} \hinline{mod x 12 == 0} \ifger{das Prädikat ist}{is the predicate}, \ifger{getrennt durch ein Komma}{separated by a comma}. \ifger{Wir können mehrere Prädikate haben}{We can have multiple predicates.}

View File

@ -1,11 +1,14 @@
Defining a pair is easy. \ifger{Ein Tuple zu definieren ist leicht:}{Defining a pair is easy.}
\begin{haskellcode} \begin{haskellcode}
p :: (Int, Char) -- this is the type p :: (Int, Char) -- this is the type
p = (2, 'y') -- this is how we construct the pair p = (2, 'y') -- this is how we construct the pair
-- pattern matching against pairs -- pattern matching against pairs
sumPair :: (Int, Int) -> Int sumPair :: (Int, Int) -> Int
sumPair (x, y) = x + y sumPair (x, y) = x + y
\end{haskellcode} \end{haskellcode}
\pause \pause
Note: we use \hinline{(x, y)} notation for both the type and the definition! Those are still two different things. We can also have triples, quadruples etc. \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?}

View File

@ -0,0 +1,13 @@
\ifger{In Haskell wird häufig das sogenannte}{In haskell we often use} \textbf{pattern matching}\ifger{ benutzt.}{.} \ifger{Das bedeutet, dass wir eine Funktion mehrmals definieren, aber z.b. für unterschiedliche Werte ihrer Eingabeargumente. Ungefähr so:}{That means we define a function multiple times, but e.g. for different values of its input arguments. Let's see:}
\pause
\begin{haskellcode}
isZero :: Int -> Bool
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.}
\vspace{\baselineskip}
\\
\pause
\ifger{Was könnte passieren wenn wir die 2. oder 3. Zeile löschen? Was ist eine}{What might happen if we remove the second or the third line? What is a} \textbf{partial function} \ifger{und eine}{and a} \textbf{total function}?

View File

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

View File

@ -1,17 +1,17 @@
\begin{itemize} \begin{itemize}
\item What are side effects? \item \ifger{was sind Seiteneffekte?}{What are side effects?}
\item What is referential transparency? \item \ifger{was ist referenzielle Transparenz?}{What is referential transparency?}
\item Can you have referential transparency with side effects? \item \ifger{kann ich referenzielle Transparenz mit Seiteneffekten haben?}{Can you have referential transparency with side effects?}
\item What does the output of a haskell function depend on? \item \ifger{wovon hängt die Ausgabe einer Haskell Funktion ab?}{What does the output of a haskell function depend on?}
\item What is laziness? \item \ifger{Was ist call-by-name? Was ist call-by-need?}{What is call-by-name? What is call-by-need?}
\item When are types checked in haskell? \item \ifger{was ist}{What is} laziness?
\item What are the differences between lists and pairs? \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} \end{itemize}
Does this compile? If not, fix it. Is this a total or a partial function? \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} \begin{haskellcode}
data IntOrDouble = MkDouble Double even :: Int -> Bool
| MkInt Int f 0 = True
f 2 = True
f :: Int -> IntOrDouble f 4 = True
f 0 = 0.5
\end{haskellcode} \end{haskellcode}

View File

@ -1,4 +1,4 @@
\begin{itemize} \begin{itemize}
\item How do functions with multiple parameters look like? \item \ifger{Wie sehen Funktionen mit mehreren Argumenten aus?}{How do functions with multiple arguments look like?}
\item ... \item ...
\end{itemize} \end{itemize}

View File

@ -1,8 +1,7 @@
How to get started? You need: \ifger{Um loszulegen benötigen wir:}{How to get started? You need:}
\begin{itemize} \begin{itemize}
\item \textbf{GHC}: this is the Haskell compiler \item \textbf{GHC}: \ifger{das ist der Haskell Compiler}{this is the Haskell compiler}
\item \textbf{GHCi}: this an interactive environment of GHC, similar to the interactive ruby shell \emph{irb} \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}: a collection including GHC, GHCi and basic libraries \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}}
\end{itemize} \item \ifger{Haskell IDEs}{haskell IDEs}\footnote{\url{https://wiki.haskell.org/IDEs}}
Go to \url{https://www.haskell.org/platform}\\ \end{itemize}
For haskell IDEs, see \url{https://wiki.haskell.org/IDEs}

View File

@ -1,13 +1,13 @@
Think of haskell functions as regular \emph{mathematical} functions. \ifger{Stell dir Haskell Funktionen als ganz normale \emph{mathematische Funktionen} vor.}{Think of haskell functions as regular \emph{mathematical} functions.}
\slidep \slidep
\vspace{\baselineskip} \vspace{\baselineskip}
\begin{center} \begin{center}
\includegraphics*[scale=0.35]{./images/function-machine.png} \includegraphics*[scale=0.35]{./images/function-machine.png}
\end{center} \end{center}
\begin{itemizep} \begin{itemizep}
\item does this function write to the hard drive? \item \ifger{schreibt diese Funktion auf die Festplatte?}{does this function write to the hard drive?}
\item does the output depend on anything else except the input (e.g. time, environment, ...)? \item \ifger{hängt die Ausgabe von irgendetwas ausser der Eingabe ab (z.b. Zeit, Umgebung...)?}{does the output depend on anything else except the input (e.g. time, environment, ...)?}
\end{itemizep} \end{itemizep}
\slidep \slidep
\vspace{\baselineskip} \vspace{\baselineskip}
It's all about \emph{input} and \emph{output} of functions! And that's it. Nothing else to worry about. \ifger{Es geht tatsächlich nur um \emph{Eingabe} und \emph{Ausgabe} von Funktionen. Und sonst nichts! Wir haben keine anderen Sorgen.}{It's all about \emph{input} and \emph{output} of functions! And that's it. Nothing else to worry about.}

View File

@ -1,4 +1,4 @@
So, functional means: \ifger{Funktional bedeutet:}{So, functional means:}
\begin{itemizep} \begin{itemizep}
\item \emph{first-class} citizens: functions are values and can be used as such \item \emph{first-class} citizens: functions are values and can be used as such
\item a haskell program is what happens when \emph{expressions are evaluated}, it's not about executing instructions \item a haskell program is what happens when \emph{expressions are evaluated}, it's not about executing instructions

View File

@ -1,7 +1,10 @@
In haskell expressions are not evaluated until their results are actually needed. That has a lot of consequences, a few of them being: \ifger{Ausdrücke in Haskell werden erst evaluiert, wenn ihr Ergebnis tatsächlich benötigt wird. Das bringt viele Konsequenzen mit sich. Einige davon sind:}{In haskell expressions are not evaluated until their results are actually needed. That has a lot of consequences, a few of them being:}
\slidep \slidep
\begin{itemizep} \begin{itemizep}
\item infinite data structures are now possible (recursive and non-recursive) \item \ifger{unendliche Datenstrukturen sind möglich, sowohl rekursive als auch nicht-rekursive}{infinite data structures are now possible (recursive and non-recursive)}
\item defining new control structures by just defining a function (since not everything is evaluated... who needs if-then-else anyway?) \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 important for compositional programming and efficiency \item \ifger{sehr wichtig für die Programmierung mit Komposition (z.b. Funktionskomposition) und Effizienz}{important for compositional programming and efficiency}
\end{itemizep} \end{itemizep}
\slidep
\vspace{\baselineskip}
\ifger{Frage:}{Question:} call-by-value? call-by-reference? call-by-need?

View File

@ -1,19 +1,16 @@
\emph{Referential transparency}, as in: \emph{\ifger{Referenzielle Transparenz}{Referential transparency}}, \ifger{also}{as in}:
\slidep \slidep
\begin{itemizep} \begin{itemizep}
\item everything (variables, data structures...) is \emph{immutable} \item \ifger{alles (Variablen, Datenstrukturen)}{everything (variables, data structures...)} \ifger{ist}{is} \emph{immutable}
\item expressions never have side-effects (remember: mathematical functions) \item \ifger{Ausdrücke haben niemals Seiteneffekte (Erinnerung: mathematische Funktionen)}{expressions never have side-effects (remember: mathematical functions)}
\item same input $\mapsto$ same output... \emph{always}! \item \ifger{gleiche Eingabe}{same input} $\mapsto$ \ifger{gleiche Ausgabe}{same output}... \emph{\ifger{immer}{always}}!
\item replace a function with it's (return) value? Yes. What happens in C or java if you do that? Remember \cppinline{void pop();}? \item \ifger{wir können eine Funktion mit ihrem (Rückgabe-)Wert ersetzen... was passiert, wenn wir das in C oder java tun? (Erinnerung:}{replace a function with it's (return) value? Yes. What happens in C or java if you do that? Remember} \cppinline{void pop();}\ifger{)}{?}
\end{itemizep} \end{itemizep}
\slidep \slidep
\vspace{\baselineskip} \vspace{\baselineskip}
possible benefits? \ifger{mögliche Vorteile?}{possible benefits?}
\begin{itemizep} \begin{itemizep}
\item parallelism \item \ifger{Parallelisierung}{parallelism}
\item equational reasoning and refactoring \item \ifger{Denken in Gleichungen und hohes Refactoring-Potenzial}{equational reasoning and refactoring}
\item less bugs! \item \ifger{weniger Bugs!}{less bugs!}
\end{itemizep} \end{itemizep}
\slidep
\vspace{\baselineskip}
Question: call-by-value? call-by-reference? call-by-need?

View File

@ -1,4 +1,4 @@
Every haskell expression has a type and types are always checked at \emph{compile-time}. Programs with errors will not compile and definitely not run. \ifger{Jeder Haskell Ausdruck hat einen Typ und Typen werden immer zur \emph{Kompilierzeit} geprüft}{Every haskell expression has a type and types are always checked at \emph{compile-time}}. \ifger{Programme mit Typfehlern werden nicht kompilieren und erst recht nicht laufen.}{Programs with errors will not compile and definitely not run.}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
It is possible to simulate dynamic types however, i.e. types which may be converted to the type you need them in, following rigid rules. In the end, they are still statically type-checked (as in: the compiler always knows what's going on). \ifger{Es ist jedoch möglich dynamische Typen zu simulieren. D.h. Typen, die wir zu den Typen konvertieren möchten, die wir gerade brauchen. Dabei müssen allerdings sehr starre Regeln eingehalten werden. Am Ende gilt, dass wir trotzdem statische Typisierung haben (also: der Compiler weiss immer was los ist)}{It is possible to simulate dynamic types however, i.e. types which may be converted to the type you need them in, following rigid rules. In the end, they are still statically type-checked (as in: the compiler always knows what's going on).}

View File

@ -2,4 +2,4 @@ Haskell is a \textbf{functional}, \textbf{pure}, \textbf{lazy} and \textbf{stati
\vspace{\baselineskip} \vspace{\baselineskip}
\pause \pause
\\ \\
A few of the following facts will be white lies. But let's not worry about that. It's maybe more about "how to think in terms of haskell?" than "what is haskell?". \ifger{Ein paar der folgenden Dinge werden vermutlich Notlügen sein. Aber das soll uns nicht weiter stören. Es geht uns mehr um die Frage "Wie denke ich in Haskell"\ als "Was genau ist Haskell?".}{A few of the following facts will be white lies. But let's not worry about that. It's maybe more about "how to think in terms of haskell?" than "what is haskell?".}

View File

@ -1,9 +1,10 @@
Let's reiterate. Haskell is: \ifger{Um zusammenzufassen, Haskell ist...}{Let's reiterate. Haskell is:}
\begin{itemize} \begin{itemize}
\item functional \item \ifger{funktional}{functional}
\item pure \item pure
\item lazy \item lazy
\item statically typed (and truly type-safe) \item \ifger{statisch typisiert (und typsicher)}{statically typed (and truly type-safe)}
\item even garbage collected \item general purpose language
\item the world's finest imperative language (what??) \item \ifger{sogar}{even} garbage collected
\item \ifger{die beste imperative Programmiersprache der Welt (was??)}{the world's finest imperative language (what??)}
\end{itemize} \end{itemize}

View File

@ -1,7 +1,6 @@
\begin{itemize} \begin{itemize}
\item what haskell is \item \ifger{was ist Haskell und seine Vorteile?}{what haskell is and what advantages does it provide?}
\item how you write haskell functions \item \ifger{wie schreibe ich Haskell Funktionen?}{how you write haskell functions?}
\item how you handle lists and pairs \item \ifger{wie gehe ich mit Listen und Tuplen um?}{how you handle lists and pairs?}
\item how you do pattern matching \item \ifger{wie funktioniert pattern matching?}{how you do pattern matching?}
\item how you create your own data types
\end{itemize} \end{itemize}

View File

@ -1,15 +1,15 @@
A Haskeller might claim: haskell... \ifger{Ein Haskeller könnte behaupten: Haskell...}{A Haskeller might claim: haskell...}
\begin{itemizep} \begin{itemizep}
\item eliminates certain classes of bugs \item \ifger{eliminiert eine ganze Klasse von bugs}{eliminates certain classes of bugs}
\item not only disallows bad programs, but also defines what constitutes a bad program \item \ifger{weist schlechte Programme nicht nur zurück, sondern definiert auch was ein schlechtes Programm ausmacht}{not only disallows bad programs, but also defines what constitutes a bad program}
\item makes it easy to reason about code \item \ifger{macht es einfach Schlussfolgerungen innerhalb von Programmen zu ziehen}{makes it easy to reason about code}
\item decreases the bus-factor \item \ifger{verringert den Bus-Faktor}{decreases the bus-factor}
\item makes it possible to apply huge changes to large programs without worrying about the implicit state machine \item \ifger{erlaubt es tiefgreifende Änderungen an Programmen zu machen ohne sich über den impliziten Zustandsautomaten Gedanken zu machen}{makes it possible to apply huge changes to large programs without worrying about the implicit state machine}
\item makes it easier to program complex problems \item \ifger{macht es einfacher komplexe Probleme zu lösen}{makes it easier to solve complex problems}
\item allows for clean APIs, even without any OOP \item \ifger{erlaubt saubere APIs, sogar ohne OOP}{allows for clean APIs, even without any OOP}
\item a haskell program of 10K LOC isn't that much different to maintain as a 100K LOC \item \ifger{ein Haskell Programm mit 10k LOC ist von der Wartung her nicht anders als 100k LOC}{a haskell program of 10K LOC isn't that much different to maintain as a 100K LOC}
\item refactoring in haskell means abstraction \item \ifger{Refactoring in Haskell bedeutet Abstraktion}{refactoring in haskell means abstraction}
\end{itemizep} \end{itemizep}
\vspace{\baselineskip} \vspace{\baselineskip}
\slidep \slidep
We'll have to see if this holds true. \ifger{Wir werden sehen, ob all dies zutrifft.}{We'll have to see if this holds true.}

View File

@ -1,9 +1,9 @@
From C++ std: \ifger{Aus der C++ Standard library}{From C++ std}:
\begin{cppcode} \begin{cppcode}
void pop(); void pop();
\end{cppcode} \end{cppcode}
\pause \pause
From the C FLINT library: \ifger{Aus der}{From the} C FLINT library:
\begin{ccode} \begin{ccode}
void fmpz_mod_poly_add( void fmpz_mod_poly_add(
fmpz_mod_poly_t res, fmpz_mod_poly_t res,
@ -12,12 +12,12 @@ void fmpz_mod_poly_add(
\end{ccode} \end{ccode}
\vspace{\baselineskip} \vspace{\baselineskip}
\pause \pause
Regular C functions in real-world (omitting examples on purpose): \ifger{Reguläre C-Funktionen im Alltag (Beispiele absichtlich unterschlagen)}{Regular C functions in real-world (omitting examples on purpose):}
\begin{itemizep} \begin{itemizep}
\item 100+ LOC \item 100+ LOC
\item at least 7 ifs, 4 whiles, 12 variables, 1 goto \item \ifger{mindestens}{at least} 7 ifs, 4 whiles, 12 variables, 1 goto
\item accesses both static and global variables \item \ifger{greift sowohl auf statisch als auch auf globale Variablen zu}{accesses both static and global variables}
\item indenting level of 5 or more \item indenting level \ifger{von 5 oder mehr}{of 5 or more}
\item a lot of memory management and custom-made error handling \item \ifger{viel Speicherverwaltung und programmspezifisches Error-Handling}{a lot of memory management and custom-made error handling}
\item references everywhere! \item \ifger{überall Referenzen!}{references everywhere!}
\end{itemizep} \end{itemizep}

View File

@ -1,13 +1,13 @@
You need to change only one single line in such a C function. You have to know: \ifger{Wir müssen nur eine einzige Zeile in dieser C Funktionen ändern. Dafür sollten wir wissen:}{You need to change only one single line in such a C function. You have to know:}
\begin{itemizep} \begin{itemizep}
\item does the order of function calls matter? \item \ifger{spielt die Reihenfolge der Funktionen eine Rolle?}{does the order of function calls matter?}
\item how does the change effect the memory management? Do we have memory leaks? Do we access invalid memory? \item \ifger{wie beeinflusst die Änderung die Speicherverwaltung? Haben wir memory leaks? Greifen wir auf unerlaubte Speicherbereiche zu?}{how does the change effect the memory management? Do we have memory leaks? Do we access invalid memory?}
\item does it change the state of static or global variables? \item \ifger{ändern wir den Zustand von statischen oder globalen Variablen?}{does it change the state of static or global variables?}
\item does it change the state of out-parameters? \item \ifger{ändern wir den Zustand von out-parametern?}{does it change the state of out-parameters?}
\item if it changes any of those states, is the function still correct? \item \ifger{wenn wir irgendeine dieser Zustände ändern, ist die Funktion immer noch korrekt?}{if it changes any of those states, is the function still correct?}
\item what happens if the program flow reaches this code-path with variable X in that particular state, while variable Z is NULL, and... \item \ifger{was passiert wenn der Programmfluss diesen Code-Pfad erreicht mit Variable X in diesem Zustand, während Variable Z NULL ist und...}{what happens if the program flow reaches this code-path with variable X in that particular state, while variable Z is NULL, and...}
\item did you just nuke a small former Soviet state? \item \ifger{haben wir gerade einen ehemaligen Sovjetstaat bombardiert?}{did you just nuke a small former Soviet state?}
\end{itemizep} \end{itemizep}
\vspace{\baselineskip} \vspace{\baselineskip}
\slidep \slidep
Conclusion: you really need to understand the complete environment of that line/function. \ifger{Schlussfolgerung: wir müssen tatsächlich die vollständige Umgebung der Zeile/Funktion verstehen.}{Conclusion: you really need to understand the complete environment of that line/function.}

View File

@ -1,7 +1,7 @@
But java helps! Does it? \ifger{Kann Java hier Abhilfe schaffen?}{But java helps! Does it?}
Sort of, because: \ifger{Ein wenig, denn:}{Sort of, because:}
\begin{itemizep} \begin{itemizep}
\item it improves APIs compared to C, since you can hide or encapsulate information in the state of an object \item \ifger{es ermöglicht bessere APIs im Vergleich zu C, da wir Informationen im Zustand eines Objektes verstecken bzw. kapseln können}{it improves APIs compared to C, since you can hide or encapsulate information in the state of an object}
\item it has a garbage collector, so you don't need to worry too much about memory \item \ifger{es hat einen garbage collector, also müssen wir uns nicht allzu viele Sorgen um die Speicherverwaltung machen}{it has a garbage collector, so you don't need to worry too much about memory}
\item an experienced programmer will find it easier to manage side-effects in Java, because you can e.g. have every impure functions throw an IO exception \item \ifger{ein erfahrener Programmierer wird es teilweise einfacher finden Seiteneffekte in Java zu bewältigen, denn er kann für jede behaftete Funktion IO exceptions schmeissen}{an experienced programmer will find it easier to manage side-effects in Java, because you can e.g. have every impure functions throw an IO exception}
\end{itemizep} \end{itemizep}

View File

@ -1,12 +1,12 @@
Unfortunately, with java we: \ifger{Leider hat Java auch einige Probleme:}{Unfortunately, with java we:}
\begin{itemizep} \begin{itemizep}
\item now got even more states to keep track of (intellectual complexity?) \item \ifger{wir müssen uns jetzt um noch mehr Zustände kümmern (intellektuelle Komplexität?)}{now got even more states to keep track of (intellectual complexity?)}
\item have clouded the program flow... it's now about object-interaction with their explicit and implicit states and because of the increase of indirection, it might get even harder to do actual abstraction \item \ifger{wir haben den Programmfluss verschleiert... jetzt geht es um Objektinteraktion mit ihren impliziten und expliziten Zuständen und aufgrund des erhöhten Levels an Indirektion wird es teilweise noch schwieriger zu abstrahieren}{have clouded the program flow... it's now about object-interaction with their explicit and implicit states and because of the increase of indirection, it might get even harder to do actual abstraction}
\item still have \textbf{side effects} everywhere: one object changes the state of another and vice versa, may arbitrarily write to the hard drive, do kernel calls or launch a missile \item \ifger{wir haben immer noch \textbf{Seiteneffekte} überall: ein Objekt ändert den Zustand eines anderen und umgekehrt, könnte zufällig auf die Festplatte schreiben, den Kernel ansprechen oder eine Rakete starten}{still have \textbf{side effects} everywhere: one object changes the state of another and vice versa, may arbitrarily write to the hard drive, do kernel calls or launch a missile}
\end{itemizep} \end{itemizep}
\slidep \slidep
Some parts of the implicit state machine have been made explicit by modelling classes, but it's still there and we have to deal with it, because we are modelling everything around states. Wouldn't it be nice if we could just forget about the global state machine? Maybe there is even a way to remove side effects and have more "predictability"? \ifger{Einige Teile der impliziten Zustandsmaschine haben wir explizit gemacht durch das modellieren von Klassen, aber sie ist immer noch da und wir müssen damit umgehen, weil wir alles um Zustände herum modellieren. Wäre es nicht schön, wenn wir die implizite Zustandsmaschine einfach vergessen könnten? Vielleicht gibt es sogar einen Weg Seiteneffekte vollständig zu entfernen, um mehr Vorhersagbarkeit zu haben?}{Some parts of the implicit state machine have been made explicit by modelling classes, but it's still there and we have to deal with it, because we are modelling everything around states. Wouldn't it be nice if we could just forget about the global state machine? Maybe there is even a way to remove side effects and have more "predictability"?}
\slidep \slidep
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
We are lucky. There is. It's called \textbf{Haskell}. \ifger{Wir haben Glück. Die Antwort ist: \textbf{Haskell}}{We are lucky. There is. It's called \textbf{Haskell}.}

View File

@ -5,15 +5,15 @@
% title page information % title page information
\author{Julian Ospald} \author{Julian Ospald}
\institute{FH Bielefeld} \institute{FH Bielefeld}
\title{Haskell: higher order functions} \title{Haskell: \ifger{Funktionen höherer Ordnung}{higher order functions}}
\begin{document} \begin{document}
\frame{\titlepage} \frame{\titlepage}
\begin{frame} \begin{frame}
\frametitle{Table of Contents} \frametitle{\ifger{Inhaltsverzeichnis}{Table of Contents}}
\tableofcontents[hidesubsections=true] \tableofcontents[hidesubsections=true,subsubsectionstyle=hide]
\end{frame} \end{frame}
\input{./VL2_document_structure.tex} \input{./VL2_document_structure.tex}

View File

@ -1,19 +1,20 @@
\section{Reiteration} \section{\ifger{Rückblick}{Reiteration}}
\slidetoc \slidetoc
\slide{./content/VL2_reiteration.tex} \slide{./content/VL2_reiteration.tex}
\section{Polymorphism} \section{\ifger{Polymorphie}{Polymorphism}}
\slidetoc \slidetoc
\slide{./content/VL2_polymorphism1.tex} \slide{./content/VL2_polymorphism1.tex}
\slide{./content/VL2_polymorphism2.tex}[ (cnt.)] \slide{./content/VL2_polymorphism2.tex}[ (cnt.)]
\slide{./content/VL2_polymorphism3.tex}[ (cnt.)]
\section{More ways to define functions} \section{\ifger{Andere Arten der Funktionsdefinition}{More ways to define functions}}
\slidetoc \slidetoc
@ -31,7 +32,7 @@
\slide{./content/VL2_let_vs_where.tex} \slide{./content/VL2_let_vs_where.tex}
\subsection{Anonymous functions} \subsection{\ifger{Anonyme Funktionen}{Anonymous functions}}
\slide{./content/VL2_anonymous_functions.tex} \slide{./content/VL2_anonymous_functions.tex}
@ -45,26 +46,27 @@
\slide{./content/VL2_currying2.tex} \slide{./content/VL2_currying2.tex}
\subsection{Mathematical example} \subsection{\ifger{Mathematisches Beispiel}{Mathematical example}}
\slide{./content/VL2_currying3.tex} \slide{./content/VL2_currying3.tex}
\subsection{Geometrical example} \subsection{\ifger{Geometrisches Beispiel}{Geometrical example}}
\slide{./content/VL2_currying4.tex} \slide{./content/VL2_currying4.tex}
\subsection{Conclusion} \subsection{\ifger{Schlussfolgerung}{Conclusion}}
\slide{./content/VL2_currying5.tex} \slide{./content/VL2_currying5.tex}
\slide{./content/VL2_currying5.1.tex}[ (cnt.)]
\subsection{Partial application} \subsection{Partial application}
\slide{./content/VL2_currying6.tex} \slide{./content/VL2_currying6.tex}
\subsection{Curry and Uncurry} \subsection{Curry \ifger{und}{and} Uncurry}
\slide{./content/VL2_currying7.tex} \slide{./content/VL2_currying7.tex}
\subsection{Summary} \subsection{\ifger{Zusammenfassung Currying}{Summary currying}}
\slide{./content/VL2_currying8.tex} \slide{./content/VL2_currying8.tex}
\section{Function composition} \section{\ifger{Funktionskomposition}{Function composition}}
\slidetoc \slidetoc
@ -73,7 +75,7 @@
\slide{./content/VL2_composition3.tex}[ (cnt.)] \slide{./content/VL2_composition3.tex}[ (cnt.)]
\section{Recursion patterns} \section{\ifger{Rekursionsstrukturen}{Recursion patterns}}
\slidetoc \slidetoc
@ -99,22 +101,25 @@
\slide{./content/VL2_fold2.tex}[ (cnt.)] \slide{./content/VL2_fold2.tex}[ (cnt.)]
\slide{./content/VL2_fold3.tex}[ (cnt.)] \slide{./content/VL2_fold3.tex}[ (cnt.)]
\slide{./content/VL2_fold4.tex}[ (cnt.)] \slide{./content/VL2_fold4.tex}[ (cnt.)]
\slide{./content/VL2_fold5.tex}[ (cnt.)]
\subsection{\ifger{Zusammenfassung Rekurssionsstrukturen}{Summary recursion patterns}}
\slide{./content/VL2_fold5.tex}
\section{Reflection} \section{\ifger{Reflexion}{Reflection}}
\slidetoc \slidetoc
\subsection{What you should know} \subsection{\ifger{Was Sie wissen sollten}{What you should know}}
\slide{./content/VL2_what_you_should_know.tex} \slide{./content/VL2_what_you_should_know.tex}
\subsection{Questions for you} \subsection{\ifger{Fragen an Sie}{Questions for you}}
\slide{./content/VL2_questions_for_you.tex} \slide{./content/VL2_questions_for_you.tex}
\section{References} \section{\ifger{Referenzen}{References}}
\slidetoc \slidetoc
@ -122,6 +127,6 @@
\slide{../common/content/VL_links.tex} \slide{../common/content/VL_links.tex}
\subsection{Sources} \subsection{\ifger{Quellen}{Sources}}
\slide{../common/content/VL_sources.tex} \slide{../common/content/VL_sources.tex}

View File

@ -6,7 +6,7 @@
% title page information % title page information
\author{Julian Ospald} \author{Julian Ospald}
\title{Haskell: higher order functions} \title{Haskell: \ifger{Funktionen höherer Ordnung}{higher order functions}}
\maketitle \maketitle

View File

@ -1,12 +1,12 @@
We can also have \textbf{anonymous functions} which just means the function doesn't have a name: \ifger{Wir können auch \textbf{anonyme Funktionen} haben, was eigentlich nur bedeutet, dass die Funktion keinen Namen hat:}{We can also have \textbf{anonymous functions} which just means the function doesn't have a name:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int f :: Int -> Int
f x = (\y -> y + 1) x f x = (\y -> y + 1) x
\end{haskellcode} \end{haskellcode}
\pause \pause
Although this is basically the same as: \ifger{Wobei dies praktisch dasselbe ist wie:}{Although this is basically the same as:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int f :: Int -> Int
f x = x + 1 f x = x + 1
\end{haskellcode} \end{haskellcode}
Anonymous functions will come extremely handy later, you'll see. \ifger{Anonyme Funktionen werden für uns später sehr nützlich sein.}{Anonymous functions will come extremely handy later, you'll see.}

View File

@ -1,12 +1,12 @@
So why did we just bother so long with explaining currying? It's because it's very important for \emph{function composition}. Which again is also one of the fundamental concepts of functional programming. \ifger{Wieso haben wir uns so lange mit Currying aufgehalten? Nun, es ist wie gesagt sehr wichtig für \emph{Funktionskomposition}. Sie zählt ebenfalls zu den fundamentalen Basiskonzepten der funktionalen Programmierung.}{So why did we just bother so long with explaining currying? It's because it's very important for \emph{function composition}. Which again is also one of the fundamental concepts of functional programming.}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
From maths we already know that:\\ \ifger{Aus der Mathematik wissen wir bereits, dass:}{From maths we already know that:}\\
$(g \circ f)(x) = g(f(x))$ $(f \circ g)(x) = f(g(x))$
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
And that's basically it. We do the same in haskell, it looks like this: \ifger{Und das ist praktisch schon alles. Wir machen dasselbe in Haskell:}{And that's basically it. We do the same in haskell, it looks like this:}
\begin{haskellcode} \begin{haskellcode}
composedFunction x = (f . g) x composedFunction x = (f . g) x
@ -14,7 +14,7 @@ composedFunction x = (f . g) x
-- is evaluated first -- is evaluated first
composedFunction x = f . g $ x composedFunction x = f . g $ x
-- and same again, remember that 'f x =' -- and same again, remember that 'g x ='
-- is just syntax sugar -- is just syntax sugar
-- omitting the x here is also called eta reduction -- omitting the x here is also called eta reduction
composedFunction = f . g composedFunction = f . g

View File

@ -1,17 +1,17 @@
But let's not stop here. What does the dot \hinline{(.)} actually mean? \ifger{Aber das soll uns nicht genug sein. Was bedeutet dieser Punkt \hinline{(.)} tatsächlich?}{But let's not stop here. What does the dot \hinline{(.)} actually mean?}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
It's just a function (the \emph{prefix} version of \hinline{.})! Here is the type signature: \ifger{Es ist einfach nur eine Funktion (die \emph{Prefix} Variante von \hinline{.})!}{It's just a function (the \emph{prefix} version of \hinline{.})! Here is the type signature:}
\begin{haskellcode} \begin{haskellcode}
(.) :: (b -> c) -> (a -> b) -> a -> c (.) :: (b -> c) -> (a -> b) -> a -> c
\end{haskellcode} \end{haskellcode}
\pause \pause
\textbf{Exercise:} Implement it! It's really just one line! Remember the mathematical definition. \textbf{\ifger{Aufgabe:}{Exercise:}} \ifger{Implementiert es! Es ist tatsächlich nur eine Zeile. Erinnert Euch an die mathematische Definition.}{Implement it! It's really just one line! Remember the mathematical definition.}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
Solution: \ifger{Lösung:}{Solution:}
\begin{haskellcode} \begin{haskellcode}
(.) :: (b -> c) -> (a -> b) -> a -> c (.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x) (.) f g x = f (g x)

View File

@ -1,4 +1,4 @@
And now you can chain functions together. Not just two! Look: \ifger{Und jetzt können wir Funktionen verketten, egal wieviele:}{And now you can chain functions together. Not just two! Look:}
\begin{haskellcode} \begin{haskellcode}
f :: String -> Bool f :: String -> Bool
f xs = (even . length . (\x -> x ++ "Hello world")) xs f xs = (even . length . (\x -> x ++ "Hello world")) xs
@ -7,7 +7,7 @@ f xs = even . length . (\x -> x ++ "Hello world") $ xs
\end{haskellcode} \end{haskellcode}
% $ % $
\pause \pause
Another example where currying is actually important: \ifger{Ein anderes Beispiel, bei dem Currying tatsächlich relevant ist:}{Another example where currying is actually important:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Bool f :: Int -> Bool
f x = even . (+) 3 . (-) 4 $ x f x = even . (+) 3 . (-) 4 $ x
@ -17,9 +17,9 @@ f x = even . (+) 3 . (-) $ 4 x
\end{haskellcode} \end{haskellcode}
%$ %$
\pause \pause
So there are a few things that we have to be aware of: \ifger{Aber es gilt hier einige wichtige Dinge zu beachten:}{So there are a few things that we have to be aware of:}
\begin{itemize} \begin{itemize}
\item the types have to fit! \item \ifger{die Typen müssen passen!}{the types have to fit!}
\item the arity has to fit! \item \ifger{die Arität muss passen!}{the arity has to fit!}
\end{itemize} \end{itemize}
That sounds complicated at first, because it counts for the whole composition chain. But you'll get used to it. \ifger{Das klingt anfangs kompliziert, weil es für die gesamte Verkettung gilt, aber man kommt sehr schnell rein.}{That sounds complicated at first, because it counts for the whole composition chain. But you'll get used to it.}

View File

@ -1,13 +1,13 @@
This is what actually makes haskell such a fine functional language. You might have noticed that I tried hard to not show type signatures of functions that have more than one argument. Well, that's because we have to dig a little deeper to explain what comes next: \ifger{Dies ist, was aus Haskell eine so wunderbare funktionale Sprache macht. In der letzten Vorlesung habe ich bewusst vermieden Funktionen mit mehreren Argumenten zu zeigen. Das liegt daran, dass wir ein bisschen weiter ausholen müssen für das, was jetzt kommt:}{This is what actually makes haskell such a fine functional language. You might have noticed that I tried hard to not show type signatures of functions that have more than one argument. Well, that's because we have to dig a little deeper to explain what comes next:}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
addInt :: Int -> Int -> Int addInt :: Int -> Int -> Int
addInt x y = x + y addInt x y = x + y
\end{haskellcode} \end{haskellcode}
\pause \pause
So, what is happening here? You probably expected something like: \ifger{Was ist hier passiert? Eher hätte man vermutlich sowas erwartet:}{So, what is happening here? You probably expected something like:}
\begin{haskellcode} \begin{haskellcode}
addInt :: (Int, Int) -> Int addInt :: (Int, Int) -> Int
addInt (x, y) = x + y addInt (x, y) = x + y
\end{haskellcode} \end{haskellcode}
which is actually pretty close. \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}.}

View File

@ -1,4 +1,4 @@
Currying is sort of a mathematical thing and is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple) into evaluating a sequence of functions, each with a single argument. \ifger{Currying ist eigentlich eine mathematische Sache und ist auf wikipedia wie folgt definiert: }{Currying is sort of a mathematical thing and is defined on wikipedia as:} \\''Currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple) into evaluating a sequence of functions, each with a single argument.'' -- Wikipedia
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
Let that sink in a little bit and read it again. \ifger{Darüber müssen wir erstmal nachdenken.}{Let that sink in a little bit and read it again.}

View File

@ -1,18 +1,23 @@
Maybe a mathematical example will make things clearer. Let's say we have the function:\\ \ifger{Vielleicht hilft ein mathematisches Beispiel die Dinge klarer zu machen. Wir haben z.b. folgende Funktion:}{Maybe a mathematical example will make things clearer. Let's say we have the function:}\\
$f(x, y) = y / x$ $f(x, y) = y / x$
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
In order to evaluate the function for $x = 2$ and $y = 3$ we would do:\\ \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) = 2 / 3$\\ $f(2, 3) = 3 / 2$
and be done.
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
However, how about we just put in x first and make a new function. Since x is gone, we can write:\\ \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:}\\
$g(y) = f(2, y) = y / 2$ $h(x) = y \mapsto f(x, y)$\\
\ifger{Dies ist bereits die curried Variante von $f$!}{This is a curried version of $f$!}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
And in a second step we solve the function $g(y)$:\\ \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)$:}\\
$g(3) = f (2, 3) = 3 / 2$ $g(3) = f (2, 3) = 3 / 2$

View File

@ -1,7 +1,5 @@
You can also imagine this geometrically:\\ \ifger{Wir können uns das ganze auch geometrisch vorstellen:}{You can also imagine this geometrically:}\\
$z = f(x, y)$ is 3-dimensional. 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$. $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$.}\\
\vspace{\baselineskip} \includegraphics*[width=0.5\textwidth]{./images/Grafico_3d_x2+xy+y2.png}
\\ \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.}
\\
For every of these steps we can define a real new function. This scales up to any number of dimensions/arguments.

View File

@ -0,0 +1,16 @@
\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

@ -1,14 +1,14 @@
So in mathematical terms you can say:\\ \ifger{D.h. mathematisch gesehen können wir schreiben:}{So in mathematical terms you can say:}\\
$f : A_1 \times ... \times A_n \mapsto B$ $f : A_1 \times ... \times A_n \mapsto B$
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
gets modified into:\\ \ifger{wird zu}{gets modified into:}\\
\pause \pause
$f' : A_1 \mapsto (A_2 \mapsto (\ ...\ (A_n \mapsto B)))$ $f' : A_1 \mapsto (A_2 \mapsto (\ ...\ (A_n \mapsto B)))$
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
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: \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:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int -> Int f :: Int -> Int -> Int
f :: Int -> (Int -> Int) f :: Int -> (Int -> Int)
@ -16,4 +16,6 @@ f :: Int -> (Int -> Int)
-- but this is NOT the same -- but this is NOT the same
f :: (Int -> Int) -> Int f :: (Int -> Int) -> Int
\end{haskellcode} \end{haskellcode}
On the other hand function application is \emph{left}-associative, so \hinline{f 3 2} is just a shorthand of \hinline{(f 3) 2}. Makes sense? \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}
\\

View File

@ -1,19 +1,16 @@
What does that mean for us? It's not just fun stuff or aesthetic. It allows us to do \textbf{partial application}. That means we do not have to give a function all arguments. If we pass an "insufficient" number of arguments it will just give us a new function! Here: \ifger{Was bedeutet das für uns? Es ermöglicht uns \textbf{partial application}, was bedeutet, dass wir einer Funktion nicht alle Argumente übergeben müssen. Wenn wir ''zu wenig'' Argumente übergeben, wird einfach eine neue Funktion generiert. Z.b. so:}{What does that mean for us? It's not just fun stuff or aesthetic. It allows us to do \textbf{partial application}. That means we do not have to give a function all arguments. If we pass an "insufficient" number of arguments it will just give us a new function! Here:}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
addInt :: Int -> Int -> Int addInt :: Int -> Int -> Int
addInt x y = x + y addInt x y = x + y
-- which is equivalent to this as we already know
addInt = \x -> (\y -> x + y)
addTwo :: Int -> Int addTwo :: Int -> Int
addTwo = addInt 2 addTwo = addInt 2
\end{haskellcode} \end{haskellcode}
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. \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.
\pause \vspace{\baselineskip}\\
The reason we can omit the \hinline{x} here is that 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.
\begin{haskellcode} \vspace{\baselineskip}\\
f x y z = ... Or in other words: we just gave the intermediate function that currying created for us the name \hinline{addTwo}. That's it.}\vspace{\baselineskip}\\
\end{haskellcode}
is just syntax sugar for
\begin{haskellcode}
f = \x -> (\y -> (\z -> ... )) -- right-associative, ofc
\end{haskellcode}

View File

@ -1,10 +1,10 @@
As said in the beginning of this section, these two look pretty similar: \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:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int -> Int f :: Int -> Int -> Int
f :: (Int, Int) -> Int f :: (Int, Int) -> Int
\end{haskellcode} \end{haskellcode}
And we now know that we can convert from one to another. Of course haskell also provides us two functions to do that, here we go: \ifger{Da wir jetzt wissen, dass man von der einen Form in die andere und zurück konvertieren kann, müssten wir dann nicht auch Funktionen dafür haben? Haben wir:}{And we now know that we can convert from one to another. Of course haskell also provides us two functions to do that, here we go:}
\begin{haskellcode} \begin{haskellcode}
curry :: ((a, b) -> c) -> a -> b -> c curry :: ((a, b) -> c) -> a -> b -> c

View File

@ -1,6 +1,6 @@
So... now that we know what currying is, let's summarize: \ifger{Zusammenfassend lässt sich über Currying sagen:}{So... now that we know what currying is, let's summarize:}
\begin{itemizep} \begin{itemizep}
\item all functions in haskell have only one argument (strictly speaking) \item \ifger{alle Funktionen in Haskell haben nur ein Argument (streng genommen)}{all functions in haskell have only one argument (strictly speaking)}
\item if a function seems to have multiple arguments... currying is used behind the scenes to evaluate it \item \ifger{wenn eine Funktion scheinbar mehrere Argumente hat steckt immer Currying dahinter um die Funktion zu evaluieren}{if a function seems to have multiple arguments... currying is used behind the scenes to evaluate it}
\item currying also allows us to do partial function application (which is important for function composition) \item \ifger{Currying erlaubt uns auch \emph{partial function application} (was auch sehr wichtig für Funktionskomposition ist)}{currying also allows us to do partial function application (which is important for function composition)}
\end{itemizep} \end{itemizep}

View File

@ -1,8 +1,8 @@
Imagine we want to filter all even numbers of a list and throw away all others. I'll give you the type signature: \ifger{Stellen wir uns vor wir wollen alle geraden Zahlen einer Liste und alle anderen nicht. Hier wäre die Typsignatur:}{Imagine we want to filter all even numbers of a list and throw away all others. I'll give you the type signature:}
\begin{haskellcode} \begin{haskellcode}
filterEven :: [Int] -> [Int] filterEven :: [Int] -> [Int]
\end{haskellcode} \end{haskellcode}
Solution? \ifger{Lösung?}{Solution?}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
filterEven :: [Int] -> [Int] filterEven :: [Int] -> [Int]
@ -12,7 +12,7 @@ filterEven (x:xs)
| otherwise = filterEven xs | otherwise = filterEven xs
\end{haskellcode} \end{haskellcode}
\pause \pause
Or: filter out all 0's, so we can count them later: \ifger{Oder: wir filtern alle $0$en, damit wir sie später zählen können:}{Or: filter out all $0$'s, so we can count them later:}
\begin{haskellcode} \begin{haskellcode}
filterZero :: [Int] -> [Int] filterZero :: [Int] -> [Int]
filterZero [] = [] filterZero [] = []
@ -20,4 +20,4 @@ filterZero (x:xs)
| x == 0 = x : filterZero xs | x == 0 = x : filterZero xs
| otherwise = filterZero xs | otherwise = filterZero xs
\end{haskellcode} \end{haskellcode}
Again: do you notice something? \ifger{Erneut: Fällt etwas auf?}{Again: do you notice something?}

View File

@ -1,14 +1,14 @@
Let's abstract out the common pieces! This will be our type signature: \ifger{Wir werden die Rekursionsstruktur erneut herausabstrahieren! Die Typsignatur sieht so aus:}{Let's abstract out the common pieces! This will be our type signature:}
\begin{haskellcode} \begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a] filter :: (a -> Bool) -> [a] -> [a]
\end{haskellcode} \end{haskellcode}
Solution? \ifger{Lösung?}{Solution?}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a] filter :: (a -> Bool) -> [a] -> [a]
filter f [] = [] filter f [] = []
filter f (x:xs) filter f (x:xs)
| f x = x : filter f xs | f x = x : filter f xs
| otherwise = filter f xs | otherwise = filter f xs
\end{haskellcode} \end{haskellcode}
Again: this function is part of the \emph{Prelude} as well. \ifger{Diese Funktion ist ebenfalls Teil von \emph{Prelude}.}{Again: this function is part of the \emph{Prelude} as well.}

View File

@ -1,25 +1,25 @@
There's one more important recursion pattern. Imagine you want the sum of all numbers of a list, so the function type signature would be: \ifger{Es gibt noch eine weitere sehr wichtige Rekursionsstruktur. Stellen wir uns vor wir wollen alle Zahlen einer Liste aufsummieren. Die Typsignatur sieht wie folgt aus:}{There's one more important recursion pattern. Imagine you want the sum of all numbers of a list, so the function type signature would be:}
\begin{haskellcode} \begin{haskellcode}
sum :: [Int] -> Int sum :: [Int] -> Int
\end{haskellcode} \end{haskellcode}
Solution? \ifger{Lösung?}{Solution?}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
sum :: [Int] -> Int sum :: [Int] -> Int
sum [] = 0 sum [] = 0
sum (x:xs) = x + sum xs sum (x:xs) = x + sum xs
\end{haskellcode} \end{haskellcode}
\pause \pause
Or the product: \ifger{Oder das Produkt:}{Or the product:}
\begin{haskellcode} \begin{haskellcode}
prod :: [Int] -> Int prod :: [Int] -> Int
prod [] = 1 prod [] = 1
prod (x:xs) = x * prod xs prod (x:xs) = x * prod xs
\end{haskellcode} \end{haskellcode}
\pause \pause
Or the length: \ifger{Oder die Länge:}{Or the length:}
\begin{haskellcode} \begin{haskellcode}
length :: [a] -> Int length :: [a] -> Int
length [] = 0 length [] = 0
length (x:xs) = 1 + length xs length (x:xs) = 1 + length xs
\end{haskellcode} \end{haskellcode}

View File

@ -1,19 +1,19 @@
To cut the story short, the abstract solution looks like this: \ifger{Um es kurz zu machen, die abstrakte Lösung ist:}{To cut the story short, the abstract solution looks like this:}
\begin{haskellcode} \begin{haskellcode}
fold :: b -> (a -> b -> b) -> [a] -> b fold :: (a -> b -> b) -> b -> [a] -> b
fold z f [] = z fold f z [] = z
fold z f (x:xs) = x `f` (fold z f xs) fold f z (x:xs) = x `f` (fold f z xs)
\end{haskellcode} \end{haskellcode}
Whoa! What's going on here?\\ Whoa! What's going on here?\\
Let's see... \ifger{Schauen wir genauer hin...}{Let's see...}
\begin{itemizep} \begin{itemizep}
\item \hinline{z} 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 \hinline{f} is our function (e.g. \hinline{(*)} 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 and the last remaining argument is the actual list we are working on \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} \end{itemizep}
\slidep \slidep
The function application has the following form:\\ \ifger{Die Funktionsanwendung hat die folgende Form:}{The function application has the following form:}\\
\hinline{fold f z [a,b,c] == a `f` (b `f` (c `f` z))} \hinline{fold f z [a,b,c] == a `f` (b `f` (c `f` z))}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
This folds from the right, so the \emph{Prelude} already defines a function which is very similar to ours and called \textbf{foldr}. \ifger{D.h. hier falten wir von rechts. \emph{Prelude} definiert diese Funktion bereits, die fast genauso ist wie unsere. Sie heisst \textbf{foldr}.}{This folds from the right, so the \emph{Prelude} already defines a function which is very similar to ours and called \textbf{foldr}.}

View File

@ -1,14 +1,14 @@
So how do our \hinline{sum}, \hinline{prod} and \hinline{length} functions look like if we use our \hinline{fold} abstraction? \ifger{Jetzt wollen wir uns unsere Funktionen}{So how do our} \hinline{sum}, \hinline{prod} \ifger{und}{and} \hinline{length} \ifger{anschauen, wenn wir sie mittels \hinline{fold} implementieren:}{functions look like if we use our \hinline{fold} abstraction?}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
sum :: [Int] -> Int sum :: [Int] -> Int
sum xs = fold 0 (\x y -> x + y) xs sum xs = fold (\x y -> x + y) 0 xs
-- a Haskeller would write -- a Haskeller would write
sum = fold 0 (+) sum = fold (+) 0
prod :: [Int] -> Int prod :: [Int] -> Int
prod xs = fold 1 (\x y -> x * y) xs prod xs = fold (\x y -> x * y) 1 xs
length :: [a] -> Int length :: [a] -> Int
length xs = fold 0 (\x y -> 1 + y) xs length xs = fold (\x y -> 1 + y) 0 xs
\end{haskellcode} \end{haskellcode}

View File

@ -1,17 +1,17 @@
There is also a function that folds from the \emph{left} which is also in the \emph{Prelude} and called \textbf{foldl}.\\ \ifger{Es gibt auch eine Funktion die von \emph{links} faltet und ebenfalls in \emph{Prelude} ist. Sie heisst \textbf{foldl}.}{There is also a function that folds from the \emph{left} which is also in the \emph{Prelude} and called \textbf{foldl}.}\\
To summarize: \ifger{Zusammenfassend:}{To summarize:}
\begin{haskellcode} \begin{haskellcode}
foldr f z [a,b,c] == a `f` (b `f` (c `f` z)) foldr f z [a,b,c] == a `f` (b `f` (c `f` z))
foldl f z [a,b,c] == ((z `f` a) `f` b) `f` c foldl f z [a,b,c] == ((z `f` a) `f` b) `f` c
\end{haskellcode} \end{haskellcode}
For \hinline{foldl} the \hinline{z} is sort of the starting value. \ifger{Für}{For} \hinline{foldl} \ifger{ist}{the} \hinline{z} \ifger{quasi der Startwert.}{is sort of the starting value.}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
We can even express foldl in terms of foldr and vice versa. If you are interested, have a look here:\\ \url{http://lambda.jstolarek.com/2012/07/expressing-foldl-in-terms-of-foldr/} \ifger{Wir können sogar foldl mittels foldr ausdrücken und umgekehrt. Wer interessiert daran ist, sollte hier\footnote{\url{http://lambda.jstolarek.com/2012/07/expressing-foldl-in-terms-of-foldr}} weiterlesen.}{We can even express foldl in terms of foldr and vice versa. If you are interested, have a look here\footnote{\url{http://lambda.jstolarek.com/2012/07/expressing-foldl-in-terms-of-foldr}}.}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
You should definitely look them up in the Prelude and play with them: \url{https://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html} \ifger{Es macht Sinn diese Funktionen in \emph{Prelude}\footnote{\url{https://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html}} anzuschauen und ein bisschen damit herumzuspielen:}{You should definitely look them up in the \emph{Prelude}\footnote{\url{https://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html}} and play with them:}
\begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi} \begin{haskellcode*}{bgcolor=mygrey,frame=single,numbers=none,label=GHCi}
> foldr (-) 0 [1, 2, 3] > foldr (-) 0 [1, 2, 3]
> foldl (-) 0 [1, 2, 3] > foldl (-) 0 [1, 2, 3]

View File

@ -1,5 +1,5 @@
\begin{itemizep} \begin{itemizep}
\item if you find recurring patterns in your code, abstract them out! Experienced Haskellers avoid explicit recursion, unless the recursion pattern is so complex/specific that an abstraction doesn't make sense. \item \ifger{Wenn wir wiederkehrende Strukturen in unserem Code finden abstrahieren wir sie heraus! Erfahrene Haskeller vermeiden explizite Rekursion, es sei denn die Rekursionsstruktur ist sehr komplex/spezifisch, sodass Abstraktion wenig Sinn macht.}{if you find recurring patterns in your code, abstract them out! Experienced Haskellers avoid explicit recursion, unless the recursion pattern is so complex/specific that an abstraction doesn't make sense.}
\item map, filter, fold etc are all dependent on the data type (here: lists). For new data types (e.g. a tree) you can and will write your own recursion abstractions \item map, filter, fold etc \ifger{hängen alle vom Datentyp ab (hier: Liste)! Für neue Datentypen (z.b. einen Tree) können und werden wir unsere eigenen Rekursionsabstraktionen schreiben}{are all dependent on the data type (here: lists)! For new data types (e.g. a tree) you can and will write your own recursion abstractions}
\item although these functions are so fundamental that they are already implemented for most data types out there \item \ifger{diese Funktionen sind jedoch so fundamental, dass sie für die meisten Datentypen schon implementiert sind}{although these functions are so fundamental that they are already implemented for most data types out there}
\end{itemizep} \end{itemizep}

View File

@ -1,4 +1,4 @@
Another way which is very similar would be using \hinline{let}: \ifger{Ein ähnlicher Weg wäre über}{Another way which is very similar would be using} \hinline{let}:
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int f :: Int -> Int
f x = let y p = x + p f x = let y p = x + p

View File

@ -1,4 +1,4 @@
These look almost the same, but they are different constructs. \hinline{where} is bound to the pattern matching \hinline{f x =} and may also have access to parts of a function that are not syntactically expressions, e.g.: \ifger{Sie ähneln sich stark, aber sind unterschiedliche Konstrukte.}{These look almost the same, but they are different constructs.} \hinline{where} \ifger{ist an das pattern matching (hier \hinline{f x ...=}) der Funktion gebunden und hat auch Zugriff auf Funktionsteile, die nicht syntaktische Ausdrücke sind, z.b.:}{is bound to the pattern matching \hinline{f x ...=} and may also have access to parts of a function that are not syntactically expressions, e.g.:}
\begin{haskellcode} \begin{haskellcode}
f x f x
| cond1 x = a | cond1 x = a
@ -7,11 +7,9 @@ f x
where where
a = w x a = w x
\end{haskellcode} \end{haskellcode}
While that is not possible with \hinline{let}, which is an actual expression and can be used whenever expressions are allowed (e.g. inside \emph{Monads}, we'll know more about these in a few weeks). \ifger{während dies mit \hinline{let} so nicht möglich ist. Dieses ist hingegen ein echter Ausdruck und kann überall dort benutzt werden, wo Ausdrücke erlaubt sind (z.b. innerhalb von \emph{Monaden}, dazu später mehr).}{While that is not possible with \hinline{let}, which is an actual expression and can be used whenever expressions are allowed (e.g. inside \emph{Monads}, we'll know more about these in a few weeks).}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
There are a few more intricacies, but most of the time this is just style consideration:\\ \url{https://wiki.haskell.org/Let_vs._Where} \ifger{Es gibt hier noch ein paar weitere Feinheiten\footnote{\url{https://wiki.haskell.org/Let_vs._Where}}, aber generell ist es einfach nur Geschmackssache.}{There are a few more intricacies\footnote{\url{https://wiki.haskell.org/Let_vs._Where}}, but most of the time this is just style consideration.}
\pause \pause
\vspace{\baselineskip} \ifger{Wie müssten wir die Funktion umschreiben um \hinline{let} zu benutzen?}{How would we have to rewrite the function in order to use \hinline{let}?}
\\
How would we have to rewrite the function in order to use \hinline{let}?

View File

@ -1,7 +1,7 @@
Let's say we have a list of \hinline{Int} and want to add \hinline{2} to every element of the list. \ifger{Stellen wir uns vor wir haben eine Liste von \hinline{Int} und wollen zu jedem Element \hinline{2} addieren.}{Let's say we have a list of \hinline{Int} and want to add \hinline{2} to every element of the list.}
\begin{haskellcode} \begin{haskellcode}
addTwo :: [Int] -> [Int] addTwo :: [Int] -> [Int]
addTwo ... ? addTwo ... ?
\end{haskellcode} \end{haskellcode}
\pause \pause
\textbf{Exercise:} Find the answer! 5 minutes time, remember the \emph{cons} operator \hinline{(:)}, pattern matching on lists and ofc recursion! Start with the case of an empty list. \textbf{\ifger{Aufgabe:}{Exercise:}} \ifger{Lösung? 5 Minuten Zeit! Nützlich könnte sein: der \emph{cons} Operator \hinline{(:)}, pattern matching und natürlich Rekursion. Startet am besten mit dem Fall einer leeren Liste.}{Find the answer! 5 minutes time, remember the \emph{cons} operator \hinline{(:)}, pattern matching on lists and ofc recursion! Start with the case of an empty list.}

View File

@ -1,23 +1,23 @@
Solution? \ifger{Lösung:}{Solution:}
\begin{haskellcode} \begin{haskellcode}
addTwo :: [Int] -> [Int] addTwo :: [Int] -> [Int]
addTwo [] = [] addTwo [] = []
addTwo (x:xs) = (x + 2) : addTwo xs addTwo (x:xs) = (x + 2) : addTwo xs
\end{haskellcode} \end{haskellcode}
\pause \pause
Now we want to square every element: \ifger{Jetzt wollen wir jedes Element quadrieren:}{Now we want to square every element:}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
square :: [Int] -> [Int] square :: [Int] -> [Int]
square [] = [] square [] = []
square (x:xs) = (x * x) : square xs square (x:xs) = (x * x) : square xs
\end{haskellcode} \end{haskellcode}
\pause \pause
Now we want the absolute of every element: \ifger{Jetzt wollen wir den Betrag jedes Elements:}{Now we want the absolute of every element:}
\begin{haskellcode} \begin{haskellcode}
absList :: [Int] -> [Int] absList :: [Int] -> [Int]
absList [] = [] absList [] = []
absList (x:xs) = (abs x) : absList xs absList (x:xs) = (abs x) : absList xs
\end{haskellcode} \end{haskellcode}
\pause \pause
Do you notice something? \ifger{Fällt etwas auf?}{Do you notice something?}

View File

@ -1,16 +1,16 @@
All those 3 functions look almost the same. Since haskell is about abstraction, we would never really write any of those like that. Instead, we will write a function that generalizes all 3. \ifger{Alle 3 Funktionen sind sehr ähnlich. In Haskell wollen wir vor allem abstrahieren und würden niemals die Funktionen derart schreiben. Stattdessen werden wir eine Funktion schreiben, die die Rekursionsstruktur aller 3 abstrakt zusammenfässt.}{All those 3 functions look almost the same. Since haskell is about abstraction, we would never really write any of those like that. Instead, we will write a function that generalizes all 3.}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
I'll give you the type signature, can you guess how the implementation looks like? \ifger{Ich gebe als Tipp die Typsignatur. Wie könnte die Implementierung aussehen?}{I'll give you the type signature, can you guess how the implementation looks like?}
\begin{haskellcode} \begin{haskellcode}
map :: (a -> b) -> [a] -> [b] map :: (a -> b) -> [a] -> [b]
\end{haskellcode} \end{haskellcode}
Solution? \ifger{Lösung?}{Solution?}
\pause \pause
\begin{haskellcode} \begin{haskellcode}
map :: (a -> b) -> [a] -> [b] map :: (a -> b) -> [a] -> [b]
map f [] = [] map f [] = []
map f (x:xs) = f x : map f xs map f (x:xs) = f x : map f xs
\end{haskellcode} \end{haskellcode}
So we don't really know what the function \hinline{f} does, but we know that it converts one element of the list to something else. We \emph{map} a function over a list! Hence the name. \ifger{Wir wissen nicht was die Funktion \hinline{f} genau macht, aber wir wissen, dass sie ein Element der Liste zu etwas anderem konvertiert. Wir \emph{mappen} eine Funktion über eine Liste! Daher der Name.}{So we don't really know what the function \hinline{f} does, but we know that it converts one element of the list to something else. We \emph{map} a function over a list! Hence the name.}

View File

@ -1,4 +1,4 @@
And now watch this: \ifger{Und jetzt definieren wir unsere ursprünglichen Funktionen mithilfe von \hinline{map}:}{And now watch this:}
\begin{haskellcode} \begin{haskellcode}
addTwo :: [Int] -> [Int] addTwo :: [Int] -> [Int]
addTwo xs = map (\x -> x + 2) xs addTwo xs = map (\x -> x + 2) xs
@ -12,4 +12,4 @@ absList xs = map (\x -> abs x) xs
absList = map abs absList = map abs
\end{haskellcode} \end{haskellcode}
\pause \pause
Cool, right? So now we have abstracted out the \textbf{recursion pattern} that is all the same for those 3 functions. \hinline{map} is actually part of the standard library (called \emph{Prelude}). \ifger{Cool, oder? Wir haben jetzt die \textbf{Rekursionsstruktur} herausabstrahiert, weil sie für alle 3 Funktionen dieselbe ist. \hinline{map} ist schon Teil des Standardmoduls \emph{Prelude}.}{Cool, right? So now we have abstracted out the \textbf{recursion pattern} that is all the same for those 3 functions. \hinline{map} is actually part of the standard library (called \emph{Prelude}).}

View File

@ -1,17 +1,17 @@
Now you know how a regular function looks like, e.g: \ifger{Jetzt wissen wir wie reguläre Funktionen aussehen, z.b.:}{Now you know how a regular function looks like, e.g:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int f :: Int -> Int
f x = x + 1 f x = x + 1
\end{haskellcode} \end{haskellcode}
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 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}.}
\pause \pause
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
Haskell allows us to \textbf{inline} functions in a few more ways, e.g.: \ifger{Haskell erlaubt uns hingegen Funktionen \emph{inline} zu definieren, z.b.:}{Haskell allows us to \textbf{inline} functions in a few more ways, e.g.:}
\begin{itemizep} \begin{itemizep}
\item with \hinline{where} \item \ifger{über}{with} \hinline{where}
\item with \hinline{let...in} \item \ifger{über}{with} \hinline{let...in}
\item anonymously (lambda abstraction) \item \ifger{anonym (lambda Abstraktion}{anonymously (lambda abstraction)}
\end{itemizep} \end{itemizep}
\slidep \slidep
A lot of Haskellers really dislike if you put non-generic functions at the top level. So you can still have atomic pieces, but inline the parts which are very specific to the current function. \ifger{Viele Haskeller mögen es nicht, wenn man nicht-generische Funktionen top-level deklariert. Denn wir können immer noch atomare Funktionsteile haben und diese aber \emph{inline} definieren, sollten sie lediglich einmal benutzte Hilfsfunktionen sein.}{A lot of Haskellers really dislike if you put non-generic functions at the top level. So you can still have atomic pieces, but inline the parts which are very specific to the current function.}

View File

@ -1,20 +1,5 @@
So when we said that haskell is good for abstraction, what did we actually mean? Do we have something like java generics or C++ templates? \ifger{Haskell eignet sich besonders gut für Abstraktion, aber wieso eigentlich? Haben wir etwas ähnliches wie java generics oder C++ templates?}{So when we said that haskell is good for abstraction, what did we actually mean? Do we have something like java generics or C++ templates?}
\vspace{\baselineskip} \vspace{\baselineskip}
\\ \\
\pause \pause
Even better! Haskell supports polymorphism for both data types and functions.\\ \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.}
Let's start with a polymorphic data type:
\begin{haskellcode}
data List t = Empty | Cons t (List t)
\end{haskellcode}
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}

View File

@ -1,20 +1,10 @@
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
\end{haskellcode}
\pause
We can even have more generic stuff like:
\begin{haskellcode}
f :: a -> b
\end{haskellcode}
Whatever the function does... it has something of one type and returns something of another type (it could be the same type, but doesn't need to). That's all we know.
\vspace{\baselineskip}
\\
\pause
Similarly, remember the function \hinline{head} which gives us the first element of a list? The type signature actually looks like this:
\begin{haskellcode} \begin{haskellcode}
head :: [a] -> a head :: [a] -> a
\end{haskellcode} \end{haskellcode}
Makes sense? \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{Frage: könnte \hinline{a} eine Funktion sein?}{Question: could \hinline{a} be a function?}

View File

@ -0,0 +1,10 @@
\ifger{Wir können sogar Funktionen schreiben wie:}{We can also have:}
\begin{haskellcode}
f :: a -> b
\end{haskellcode}
\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,17 +1,17 @@
\begin{itemize} \begin{itemize}
\item what is the difference between \hinline{let} and \hinline{where}? \item \ifger{was ist der Unterschied zwischen}{what is the difference between} \hinline{let} \ifger{und}{and} \hinline{where}?
\item what is the difference between \hinline{foldr} and \hinline{foldl}? \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 what is the difference between explicit and implicit recursion? Give examples \item \ifger{was ist der Unterschied zwischen expliziter und impliziter Rekursion? Beispiele?}{what is the difference between explicit and implicit recursion? Give examples}
\item how many arguments does a haskell function have (strictly speaking)? \item \ifger{wie viele Argumente hat eine Haskell Funktion (streng genommen)?}{how many arguments does a haskell function have (strictly speaking)?}
\item Are these type signatures technically equivalent? \item \ifger{Sind diese Typsignaturen technisch äquivalent?}{Are these type signatures technically equivalent?}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int -> Char -> Int -> Int -> Char f :: Int -> Int -> Char -> Int -> Int -> Char
f :: Int -> Int -> (Char -> (Int -> (Int -> Char))) f :: Int -> Int -> (Char -> (Int -> (Int -> Char)))
\end{haskellcode} \end{haskellcode}
% $ % $
\item what do you have to keep in mind in order to make function composition work? \item \ifger{worauf muss man beim verketten von Funktionen (Funktionskomposition) achten?}{what do you have to keep in mind in order to make function composition work?}
\item can you define \hinline{map} and \hinline{filter} in terms of \hinline{foldr}? \item \ifger{können wir}{can you define} \hinline{map} \ifger{und}{and} \hinline{filter} \ifger{mittels}{in terms of} \hinline{foldr}\ifger{ ausdrücken?}{?}
\item simplify (and eta reduce) the following code snippet \item \ifger{vereinfache (und eta reduce) den folgenden Code}{simplify (and eta reduce) the following code snippet}:
\begin{haskellcode} \begin{haskellcode}
f x y = (\d e -> d * e) x $ y f x y = (\d e -> d * e) x $ y
\end{haskellcode} \end{haskellcode}

View File

@ -1,9 +1,9 @@
Since we use lists a lot in haskell, we also want some more powerful functions to deal with them. E.g.: \ifger{Da wir in Haskell häufig Listen verwenden, wollen wir auch ein paar mächtige Funktionen kennen lernen, um mit ihnen umzugehen. Z.b.:}{Since we use lists a lot in haskell, we also want some more powerful functions to deal with them. E.g.:}
\begin{itemize} \begin{itemize}
\item perform an operation on every element on a list \item \ifger{eine Operation auf jedem Element einer Liste ausführen}{perform an operation on every element on a list}
\item keep only some elements in the list, following some criteria \item \ifger{nur einige Elemente in der Liste behalten, nach einem bestimmten Kriterium}{keep only some elements in the list, following some criteria}
\item "summarize" the elements of the list somehow \item \ifger{die Elemente einer Liste irgendwie ''zusammenfassen''}{''summarize'' the elements of the list somehow}
\item ... \item ...
\end{itemize} \end{itemize}
\pause \pause
How do we do that? \ifger{Wie könnte das aussehen?}{How do we do that?}

View File

@ -1,6 +1,5 @@
\begin{itemize} \begin{itemize}
\item What is haskell? What are the 3 fundamental concepts behind it? \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 How do you do pattern matching? \item \ifger{Wie funktioniert pattern matching?}{How do you do pattern matching?}
\item What is the difference between lists and tuples? How do you construct them? \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 How do you define your own data types?
\end{itemize} \end{itemize}

View File

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

View File

@ -1,4 +1,4 @@
We use \hinline{where} to define a helper function: \ifger{Wir benutzen}{We use} \hinline{where} \ifger{um eine Hilfsfunktion zu definieren:}{to define a helper function:}
\begin{haskellcode} \begin{haskellcode}
f :: Int -> Int f :: Int -> Int
f x = x + (y 2) f x = x + (y 2)

View File

@ -28,7 +28,7 @@
\NewDocumentCommand {\slide} { m O{} O{} } \NewDocumentCommand {\slide} { m O{} O{} }
{\begin{frame}{#3} {\begin{frame}{#3}
\frametitle{\thesection.\ifnum\thesubsection=0\else\thesubsection.\fi\ \currentname {#2}} \frametitle{\thesection.\ifnum\thesubsection=0\else\thesubsection.\fi\ifnum\thesubsubsection=0\else\thesubsubsection.\fi\ \currentname {#2}}
\input{#1} \input{#1}
\end{frame}} \end{frame}}

View File

@ -51,3 +51,9 @@ addTwo (x:xs) = (x + 2) : addTwo xs
f'' :: String -> Bool f'' :: String -> Bool
f'' xs = even . length . (\x -> x ++ "Hello world") $ xs f'' xs = even . length . (\x -> x ++ "Hello world") $ xs
g :: Int -> Bool
g x = case x - 2 of
2 -> True
5 -> True
x -> False

View File

@ -1,3 +1,9 @@
% language
\usepackage[english,german]{babel}
\usepackage{iflang}
\babeltags{de = german}
\newcommand{\ifger}[2]{\IfLanguageName{german}{#1}{#2}}
% color definition % color definition
\definecolor{solarized}{HTML}{002B36} \definecolor{solarized}{HTML}{002B36}
\definecolor{mygreen}{HTML}{009900} \definecolor{mygreen}{HTML}{009900}

View File

@ -1,8 +1,8 @@
\begin{itemize} \begin{itemize}
\item the most popular haskell course from Brent Yorgey:\\ \url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html} \item \ifger{der wohl populärste Haskell-Kurs von Brent Yorgey}{the most popular haskell course from Brent Yorgey}\footnote{\url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html}}
\item very verbose and enthusiastic haskell book, good for reading once:\\ \url{http://learnyouahaskell.com} \item \ifger{sehr ausführliches und enthusiastisches Haskell-Buch, gut zum einmal lesen.}{very verbose and enthusiastic haskell book, good for reading once.}\footnote{\url{http://learnyouahaskell.com}}
\item collection of websites teaching haskell:\\ \url{https://github.com/bitemyapp/learnhaskell} \item \ifger{eine Kollektion von Webseiten, mit deren Hilfe man Haskell lernen kann}{collection of websites teaching haskell}\footnote{\url{https://github.com/bitemyapp/learnhaskell}}
\item haskell programming tips (and wiki):\\ \url{https://wiki.haskell.org/Haskell_programming_tips} \item \ifger{Haskell Programmiertips (und wiki)}{haskell programming tips (and wiki)}\footnote{\url{https://wiki.haskell.org/Haskell_programming_tips}}
\item the standard module (similar to libc in C):\\ \url{https://hackage.haskell.org/package/base-4.7.0.0/docs/Prelude.html} \item \ifger{Das Standardmodul (ähnlich wie libc in C)}{the standard module (similar to libc in C)}\footnote{\url{https://hackage.haskell.org/package/base-4.7.0.0/docs/Prelude.html}}
\item debugging in haskell:\\ \url{https://wiki.haskell.org/Debugging} \item \ifger{debuggen in Haskell}{debugging in haskell}\footnote{\url{https://wiki.haskell.org/Debugging}}
\end{itemize} \end{itemize}

View File

@ -1,6 +1,6 @@
\begin{itemize} \begin{itemize}
\item much content was borrowed or is based on the haskell course from Brent Yorgey:\\ \url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html} \item \ifger{viel Stoff ist entlehnt von oder basiert auf dem Haskell-Kurs von Brent Yorgey}{much content was borrowed or is based on the haskell course from Brent Yorgey}\footnote{\url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html}}
\item a few small pieces from the LYAH book \url{http://learnyouahaskell.com} \item \ifger{ein paar kleinere Teile aus dem LYAH Buch}{a few small pieces from the LYAH book}\footnote{\url{http://learnyouahaskell.com}}
\item general information from wikipedia: \\ \url{https://en.wikipedia.org} \item \ifger{allgemeine Informationen von Wikipedia}{general information from wikipedia}\footnote{\url{https://en.wikipedia.org}}
\item general information from haskell wiki: \\ \url{https://wiki.haskell.org} \item \ifger{allgemeine Informationen vom Haskell Wiki}{general information from haskell wiki}\footnote{\url{https://wiki.haskell.org}}
\end{itemize} \end{itemize}