VL2: Restructure files, add proper article/handout version

This commit is contained in:
Julian Ospald 2015-04-20 00:32:50 +02:00
parent fcbb846d7e
commit 86969074e3
No known key found for this signature in database
GPG Key ID: 220CD1C5BDEED020
36 changed files with 675 additions and 503 deletions

557
VL2.tex
View File

@ -37,6 +37,10 @@
% macros and environments
\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\slidep}{\onslide<+->}
\newenvironment{itemizep}
{\begin{itemize}[<+->]}
{\end{itemize}}
\begin{document}
@ -56,12 +60,7 @@
\begin{frame}
\frametitle{1. Reiteration (ctn.)}
\begin{itemize}
\item What is haskell? What are the 3 fundamental concepts behind it?
\item How do you do pattern matching?
\item What is the difference between lists and tuples? How do you construct them?
\item How do you define your own data types?
\end{itemize}
\input{VL2_reiteration.tex}
\end{frame}
\section{2. Polymorphism}
@ -73,145 +72,52 @@
\begin{frame}[fragile]
\frametitle{2. Polymorphism (ctn.)}
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}
\\
\pause
Even better! Haskell supports polymorphism for both data types and functions.\\
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}
\input{VL2_polymorphism1.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{2. Polymorphism (ctn.)}
And now we are going to write functions to use it:
\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 \code{head} which gives us the first element of a list? The type signature actually looks like this:
\begin{haskellcode}
head :: [a] -> a
\end{haskellcode}
Makes sense?
\input{VL2_polymorphism2.tex}
\end{frame}
\section{3. More ways to define functions}
\begin{frame}
\frametitle{6. More ways to define functions}
\frametitle{3. More ways to define functions}
\tableofcontents[currentsection,hideothersubsections]
\end{frame}
\begin{frame}[fragile]
\frametitle{3. More ways to define functions (ctn.)}
Now you know how a regular function looks like, e.g:
\begin{haskellcode}
f :: Int -> Int
f x = x + 1
\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 \code{static}.
\pause
\vspace{\baselineskip}
\\
Haskell allows us to \textbf{inline} functions in a few more ways, e.g.:
\begin{itemize}[<+->]
\item with \code{where}
\item with \code{let...in}
\item anonymously (lambda abstraction)
\end{itemize}
\onslide<+->
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.
\input{VL2_define_functions1.tex}
\end{frame}
\subsection{3.1. Where}
\begin{frame}[fragile]
\frametitle{3.1. Where}
We use \code{where} to define a helper function:
\begin{haskellcode}
f :: Int -> Int
f x = x + (y 2)
where
y :: Int -> Int
y p = x + p
\end{haskellcode}
\input{VL2_define_functions2.tex}
\end{frame}
\subsection{3.2. Let}
\begin{frame}[fragile]
\frametitle{3.2. Let}
Another way which is very similar would be using \code{let}:
\begin{haskellcode}
f :: Int -> Int
f x = let y p = x + p
in x + (y 2)
\end{haskellcode}
\input{VL2_define_functions3.tex}
\end{frame}
\subsection{3.3. Let vs Where}
\begin{frame}[fragile]
\frametitle{3.3. Let vs Where}
These look almost the same, but they are different constructs. \code{where} is bound to the pattern matching \code{f x =} and may also have access to parts of a function that are not syntactically expressions, e.g.:
\begin{haskellcode}
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
\end{haskellcode}
While that is not possible with \code{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}
\\
There are a few more intricacies, but most of the time this is just style consideration:\\ \url{https://wiki.haskell.org/Let_vs._Where}
\pause
\vspace{\baselineskip}
\\
How would we have to rewrite the function in order to use \code{let}?
\input{VL2_define_functions4.tex}
\end{frame}
\subsection{3.4. Anonymous functions}
\begin{frame}[fragile]
\frametitle{3.4. Anonymous functions}
We can also have \textbf{anonymous functions} which just means the function doesn't have a name:
\begin{haskellcode}
f :: Int -> Int
f x = (\y -> y + 1) x
\end{haskellcode}
\pause
Although this is basically the same as:
\begin{haskellcode}
f :: Int -> Int
f x = x + 1
\end{haskellcode}
Anonymous functions will come extremely handy later, you'll see.
\input{VL2_define_functions5.tex}
\end{frame}
\section{4. Currying}
@ -223,131 +129,42 @@ Anonymous functions will come extremely handy later, you'll see.
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
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
\begin{haskellcode}
addInt :: Int -> Int -> Int
addInt x y = x + y
\end{haskellcode}
\pause
So, what is happening here? You probably expected something like:
\begin{haskellcode}
addInt :: (Int, Int) -> Int
addInt (x, y) = x + y
\end{haskellcode}
which is actually pretty close.
\input{VL2_currying1.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
Currying is actually 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.
\vspace{\baselineskip}
\\
Let that sink in a little bit and read it again.
\input{VL2_currying2.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
Maybe a mathematical example will make things clearer. Let's say we have the function:\\
$f(x, y) = y / x$
\vspace{\baselineskip}
\\
\pause
In order to evaluate the function for $x = 2$ and $y = 3$ we would do:\\
$f(2, 3) = 2 / 3$\\
and be done.
\vspace{\baselineskip}
\\
\pause
However, how about we just put in x first and make a new function. Since x is gone, we can write:\\
$g(y) = f(2, y) = y / 2$
\vspace{\baselineskip}
\\
\pause
And in a second step we solve the function $g(y)$:\\
$g(3) = f (2, 3) = 3 / 2$
\input{VL2_currying3.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
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$.
\vspace{\baselineskip}
\\
\includegraphics*[scale=0.4]{Grafico_3d_x2+xy+y2.png}
\\
For every of these steps we can define a real new function. This scales up to any number of dimensions/arguments.
\input{VL2_currying4.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
So in mathematical terms you can say:\\
$f : A_1 \times ... \times A_n \mapsto B$
\vspace{\baselineskip}
\\
gets modified into:\\
\pause
$f' : A_1 \mapsto (A_2 \mapsto (\ ...\ (A_n \mapsto B)))$
\vspace{\baselineskip}
\\
\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:
\begin{haskellcode}
f :: Int -> Int -> Int
f :: Int -> (Int -> Int)
\end{haskellcode}
On the other hand function application is \emph{left}-associative, so \code{f 3 2} is just a shorthand of \code{(f 3) 2}. Makes sense?
\input{VL2_currying5.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
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
\begin{haskellcode}
addInt :: Int -> Int -> Int
addInt x y = x + y
addTwo :: Int -> Int
addTwo = addInt 2
\end{haskellcode}
You probably noticed that we did not write \code{addTwo x = ...}, but why would we? We gave \code{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.
\vspace{\baselineskip}
\\
\pause
The reason we can omit the \code{x} here is that
\begin{haskellcode}
f x y z = ...
\end{haskellcode}
is just syntax sugar for
\begin{haskellcode}
f = \x -> (\y -> (\z -> ... )) -- right-associative, ofc
\end{haskellcode}
\input{VL2_currying6.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
As said in the beginning of this section, these two look pretty similar:
\begin{haskellcode}
f :: Int -> Int -> Int
f :: (Int, Int) -> Int
\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:
\begin{haskellcode}
curry :: ((a, b) -> c) -> a -> b -> c
uncurry :: (a -> b -> c) -> (a, b) -> c
\end{haskellcode}
\input{VL2_currying7.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{4. Currying (ctn.)}
So... now that we know what currying is, let's summarize:
\begin{itemize}[<+->]
\item 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 currying also allows us to do partial function application (which is important for function composition)
\end{itemize}
\input{VL2_currying8.tex}
\end{frame}
\section{5. Function composition}
@ -360,78 +177,17 @@ So... now that we know what currying is, let's summarize:
\begin{frame}[fragile]
\frametitle{5. Function composition (ctn.)}
So why did we just bother so long with explaining currying? It's because it's very important for function composition. Which again is also one of the fundamental concepts of functional programming.
\vspace{\baselineskip}
\\
From maths we already know that:\\
$(g \circ f)(x) = g(f(x))$
\vspace{\baselineskip}
\\
\pause
And that's basically it. We do the same in haskell, it looks like this:
\begin{haskellcode}
composedFunction x = (f . g) x
-- same as above... everything on the right side of $
-- is evaluated first
composedFunction x = f . g $ x
-- and same again, remember that 'f x ='
-- is just syntax sugar
-- omitting the x here is also called eta reduction
composedFunction = f . g
\end{haskellcode}
\input{VL2_composition1.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{5. Function composition}
But let's not stop here. What does the dot \code{(.)} actually mean?
\vspace{\baselineskip}
\\
\pause
It's just a function (the \emph{prefix} version of \code{.})! Here is the type signature:
\begin{haskellcode}
(.) :: (b -> c) -> (a -> b) -> a -> c
\end{haskellcode}
\pause
\textbf{Exercise:} Implement it! It's really just one line! Remember the mathematical definition.
\vspace{\baselineskip}
\\
\pause
Solution:
\begin{haskellcode}
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)
\end{haskellcode}
\input{VL2_composition2.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{5. Function composition}
And now you can chain functions together. Not just two! Look:
\begin{haskellcode}
f :: String -> Bool
f xs = (even . length . (\x -> x ++ "Hello world")) xs
-- or less ugly
f xs = even . length . (\x -> x ++ "Hello world") $ xs
\end{haskellcode}
% $
\pause
Another example where currying is actually important:
\begin{haskellcode}
f :: Int -> Bool
f x = even . (+) 3 . (-) 4 $ x
-- why not this?
f x = even . (+) 3 . (-) $ 4 x
\end{haskellcode}
%$
\pause
So there are a few things that we have to be aware of:
\begin{itemize}
\item the types have to fit!
\item the arity has to fit!
\end{itemize}
That sounds complicated at first, because it counts for the whole composition chain. But you'll get used to it.
\input{VL2_composition3.tex}
\end{frame}
\section{6. Recursion patterns}
@ -443,247 +199,68 @@ That sounds complicated at first, because it counts for the whole composition ch
\begin{frame}[fragile]
\frametitle{6. Recursion patterns (ctn.)}
Since we use lists a lot in haskell, we also want some more powerful functions to deal with them. E.g.:
\begin{itemize}
\item perform an operation on every element on a list
\item keep only some elements in the list, following some criteria
\item "summarize" the elements of the list somehow
\item ...
\end{itemize}
\pause
How do we do that?
\input{VL2_rec_patterns1.tex}
\end{frame}
\subsection{6.1. map}
\subsection{6.1. Map}
\begin{frame}[fragile]
\frametitle{6.1. map}
Let's say we have a list of \code{Int} and want to add \code{2} to every element of the list.
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo ... ?
\end{haskellcode}
\pause
\textbf{Exercise:} Find the answer! 5 minutes time, remember the \emph{cons} operator \code{(:)}, pattern matching on lists and ofc recursion! Start with the case of an empty list.
\frametitle{6.1. Map}
\input{VL2_rec_patterns2.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.1. map (ctn.)}
Solution?
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo [] = []
addTwo (x:xs) = (x + 2) : addTwo xs
\end{haskellcode}
\pause
Now we want to square every element:
\pause
\begin{haskellcode}
square :: [Int] -> [Int]
square [] = []
square (x:xs) = (x * x) : square xs
\end{haskellcode}
\pause
Now we want the absolute of every element:
\begin{haskellcode}
absList :: [Int] -> [Int]
absList [] = []
absList (x:xs) = (abs x) : absList xs
\end{haskellcode}
\pause
Do you notice something?
\frametitle{6.1. Map (ctn.)}
\input{VL2_rec_patterns3.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.1. map (ctn.)}
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}
\\
\pause
I'll give you the type signature, can you guess how the implementation looks like?
\begin{haskellcode}
map :: (a -> b) -> [a] -> [b]
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
\end{haskellcode}
So we don't really know what the function \code{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.
\frametitle{6.1. Map (ctn.)}
\input{VL2_rec_patterns4.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.1. map (ctn.)}
And now watch this:
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo xs = map (\x -> x + 2) xs
square :: [Int] -> [Int]
square xs = map (\x -> x * x) xs
absList :: [Int] -> [Int]
absList xs = map (\x -> abs x) xs
-- a haskeller would write, GHCi...
absList = map abs
\end{haskellcode}
\pause
Cool, right? So now we have abstracted out the \textbf{recursion pattern} that is all the same for those 3 functions. \code{map} is actually part of the standard library (called \emph{Prelude}).
\frametitle{6.1. Map (ctn.)}
\input{VL2_rec_patterns5.tex}
\end{frame}
\subsection{6.2. filter}
\subsection{6.2. Filter}
\begin{frame}[fragile]
\frametitle{6.2. filter}
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}
filterEven :: [Int] -> [Int]
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
filterEven :: [Int] -> [Int]
filterEven [] = []
filterEven (x:xs)
| even x = x : filterEven xs
| otherwise = filterEven xs
\end{haskellcode}
\pause
Or: filter out all 0's, so we can count them later:
\begin{haskellcode}
filterZero :: [Int] -> [Int]
filterZero [] = []
filterZero (x:xs)
| x == 0 = x : filterZero xs
| otherwise = filterZero xs
\end{haskellcode}
Again: do you notice something?
\frametitle{6.2. Filter}
\input{VL2_rec_patterns6.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.2. filter (ctn.)}
Let's abstract out the common pieces! This will be our type signature:
\begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a]
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a]
filter f [] = []
filter f (x:xs)
| f x = x : filter f xs
| otherwise = filter f xs
\end{haskellcode}
Again: this function is part of the \emph{Prelude} as well.
\frametitle{6.2. Filter (ctn.)}
\input{VL2_rec_patterns7.tex}
\end{frame}
\subsection{6.3. fold}
\subsection{6.3. Fold}
\begin{frame}[fragile]
\frametitle{6.3. fold}
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}
sum :: [Int] -> Int
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
sum :: [Int] -> Int
sum [] = 0
sum (x:xs) = x + sum xs
\end{haskellcode}
\pause
Or the product:
\begin{haskellcode}
prod :: [Int] -> Int
prod [] = 1
prod (x:xs) = x * prod xs
\end{haskellcode}
\pause
Or the length:
\begin{haskellcode}
length :: [a] -> Int
length [] = 0
length (x:xs) = 1 + length xs
\end{haskellcode}
\frametitle{6.3. Fold}
\input{VL2_rec_patterns8.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.3. fold (ctn.)}
To cut the story short, the abstract solution looks like this:
\begin{haskellcode}
fold :: b -> (a -> b -> b) -> [a] -> b
fold z f [] = z
fold z f (x:xs) = f x (fold z f xs)
\end{haskellcode}
Whoa! What's going on here?\\
Let's see...
\begin{itemize}[<+->]
\item \code{z} is what we return if the list is empty
\item \code{f} is our function (e.g. \code{(*)} or \code{(+)})
\item and the last remaining argument is the actual list we are working on
\end{itemize}
\onslide<+->
The function application has the following form:\\
\code{fold f z [a,b,c] == a `f` (b `f` (c `f` z))}
\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}.
\frametitle{6.3. Fold (ctn.)}
\input{VL2_rec_patterns9.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.3. fold (ctn.)}
So how do our \code{sum}, \code{prod} and \code{length} functions look like if we use our \code{fold} abstraction?
\pause
\begin{haskellcode}
sum :: [Int] -> Int
sum xs = fold 0 (\x y -> x + y) xs
-- a Haskeller would write
sum = fold 0 (+)
prod :: [Int] -> Int
prod xs = fold 1 (\x y -> x * y) xs
length :: [a] -> Int
length xs = fold 0 (\x y -> 1 + y) xs
\end{haskellcode}
\frametitle{6.3. Fold (ctn.)}
\input{VL2_rec_patterns10.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.3. fold (ctn.)}
There is also a function that folds from the \emph{left} which is also in the \emph{Prelude} and called \textbf{foldl}.\\
To summarize:
\begin{haskellcode}
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
\end{haskellcode}
For \code{foldl} the \code{z} is sort of the starting value.
\vspace{\baselineskip}
\\
\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/}
\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}
\vspace{\baselineskip}
\\
GHCi...
\begin{haskellcode}
> foldr (-) 0 [1, 2, 3]
> foldl (-) 0 [1, 2, 3]
\end{haskellcode}
\frametitle{6.3. Fold (ctn.)}
\input{VL2_rec_patterns11.tex}
\end{frame}
\begin{frame}[fragile]
\frametitle{6.3. summary}
\begin{itemize}[<+->]
\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 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 although these functions are so fundamental that they are already implemented for most data types out there
\end{itemize}
\frametitle{6.3. Summary}
\input{VL2_rec_patterns12.tex}
\end{frame}
\section{7. Reflection}
@ -696,28 +273,14 @@ GHCi...
\begin{frame}
\frametitle{7.1. What you should know now}
\begin{itemize}
\item how to write polymorphic data types and functions
\item how you inline functions
\item what currying is and why we need it in haskell
\item how you compose functions
\item how to abstract out recursion patterns
\end{itemize}
\input{VL2_reflection1.tex}
\end{frame}
\subsection{7.2. Questions for you}
\begin{frame}[fragile]
\frametitle{7.2. Questions for you}
\begin{itemize}
\item what is the difference between \code{let} and \code{where}?
\item what is the difference between \code{foldr} and \code{foldl}?
\item what is the difference between explicit and implicit recursion? Give examples
\item how many arguments does a haskell function have (strictly speaking)?
\item what do you have to keep in mind in order to make function composition work?
\item can you define map and filter in terms of foldr?
\item what is eta reduction (or: eta abstraction)?
\end{itemize}
\input{VL2_reflection2.tex}
\end{frame}
\section{8. References}
@ -731,26 +294,14 @@ GHCi...
\begin{frame}
\frametitle{8.1. Further reading and useful links}
\begin{itemize}
\item the most popular haskell course from Brent Yorgey:\\ \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 collection of websites teaching haskell:\\ \url{https://github.com/bitemyapp/learnhaskell}
\item haskell programming tips (and wiki):\\ \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 debugging in haskell:\\ \url{https://wiki.haskell.org/Debugging}
\end{itemize}
\input{VL_links.tex}
\end{frame}
\subsection{8.2. Sources}
\begin{frame}
\frametitle{8.2. Sources}
\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 a few small pieces from the LYAH book \url{http://learnyouahaskell.com}
\item general information from wikipedia: \\ \url{https://en.wikipedia.org}
\item general information from haskell wiki: \\ \url{https://wiki.haskell.org}
\end{itemize}
\input{VL_sources.tex}
\end{frame}
\end{document}

21
VL2_composition1.tex Normal file
View File

@ -0,0 +1,21 @@
So why did we just bother so long with explaining currying? It's because it's very important for function composition. Which again is also one of the fundamental concepts of functional programming.
\vspace{\baselineskip}
\\
From maths we already know that:\\
$(g \circ f)(x) = g(f(x))$
\vspace{\baselineskip}
\\
\pause
And that's basically it. We do the same in haskell, it looks like this:
\begin{haskellcode}
composedFunction x = (f . g) x
-- same as above... everything on the right side of $
-- is evaluated first
composedFunction x = f . g $ x
-- and same again, remember that 'f x ='
-- is just syntax sugar
-- omitting the x here is also called eta reduction
composedFunction = f . g
\end{haskellcode}

18
VL2_composition2.tex Normal file
View File

@ -0,0 +1,18 @@
But let's not stop here. What does the dot \code{(.)} actually mean?
\vspace{\baselineskip}
\\
\pause
It's just a function (the \emph{prefix} version of \code{.})! Here is the type signature:
\begin{haskellcode}
(.) :: (b -> c) -> (a -> b) -> a -> c
\end{haskellcode}
\pause
\textbf{Exercise:} Implement it! It's really just one line! Remember the mathematical definition.
\vspace{\baselineskip}
\\
\pause
Solution:
\begin{haskellcode}
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)
\end{haskellcode}

25
VL2_composition3.tex Normal file
View File

@ -0,0 +1,25 @@
And now you can chain functions together. Not just two! Look:
\begin{haskellcode}
f :: String -> Bool
f xs = (even . length . (\x -> x ++ "Hello world")) xs
-- or less ugly
f xs = even . length . (\x -> x ++ "Hello world") $ xs
\end{haskellcode}
% $
\pause
Another example where currying is actually important:
\begin{haskellcode}
f :: Int -> Bool
f x = even . (+) 3 . (-) 4 $ x
-- why not this?
f x = even . (+) 3 . (-) $ 4 x
\end{haskellcode}
%$
\pause
So there are a few things that we have to be aware of:
\begin{itemize}
\item the types have to fit!
\item the arity has to fit!
\end{itemize}
That sounds complicated at first, because it counts for the whole composition chain. But you'll get used to it.

13
VL2_currying1.tex Normal file
View File

@ -0,0 +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:
\pause
\begin{haskellcode}
addInt :: Int -> Int -> Int
addInt x y = x + y
\end{haskellcode}
\pause
So, what is happening here? You probably expected something like:
\begin{haskellcode}
addInt :: (Int, Int) -> Int
addInt (x, y) = x + y
\end{haskellcode}
which is actually pretty close.

4
VL2_currying2.tex Normal file
View File

@ -0,0 +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.
\vspace{\baselineskip}
\\
Let that sink in a little bit and read it again.

18
VL2_currying3.tex Normal file
View File

@ -0,0 +1,18 @@
Maybe a mathematical example will make things clearer. Let's say we have the function:\\
$f(x, y) = y / x$
\vspace{\baselineskip}
\\
\pause
In order to evaluate the function for $x = 2$ and $y = 3$ we would do:\\
$f(2, 3) = 2 / 3$\\
and be done.
\vspace{\baselineskip}
\\
\pause
However, how about we just put in x first and make a new function. Since x is gone, we can write:\\
$g(y) = f(2, y) = y / 2$
\vspace{\baselineskip}
\\
\pause
And in a second step we solve the function $g(y)$:\\
$g(3) = f (2, 3) = 3 / 2$

7
VL2_currying4.tex Normal file
View File

@ -0,0 +1,7 @@
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$.
\vspace{\baselineskip}
\\
\includegraphics*[scale=0.4]{Grafico_3d_x2+xy+y2.png}
\\
For every of these steps we can define a real new function. This scales up to any number of dimensions/arguments.

16
VL2_currying5.tex Normal file
View File

@ -0,0 +1,16 @@
So in mathematical terms you can say:\\
$f : A_1 \times ... \times A_n \mapsto B$
\vspace{\baselineskip}
\\
gets modified into:\\
\pause
$f' : A_1 \mapsto (A_2 \mapsto (\ ...\ (A_n \mapsto B)))$
\vspace{\baselineskip}
\\
\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:
\begin{haskellcode}
f :: Int -> Int -> Int
f :: Int -> (Int -> Int)
\end{haskellcode}
On the other hand function application is \emph{left}-associative, so \code{f 3 2} is just a shorthand of \code{(f 3) 2}. Makes sense?

21
VL2_currying6.tex Normal file
View File

@ -0,0 +1,21 @@
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
\begin{haskellcode}
addInt :: Int -> Int -> Int
addInt x y = x + y
addTwo :: Int -> Int
addTwo = addInt 2
\end{haskellcode}
You probably noticed that we did not write \code{addTwo x = ...}, but why would we? We gave \code{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.
\vspace{\baselineskip}
\\
\pause
The reason we can omit the \code{x} here is that
\begin{haskellcode}
f x y z = ...
\end{haskellcode}
is just syntax sugar for
\begin{haskellcode}
f = \x -> (\y -> (\z -> ... )) -- right-associative, ofc
\end{haskellcode}

12
VL2_currying7.tex Normal file
View File

@ -0,0 +1,12 @@
As said in the beginning of this section, these two look pretty similar:
\begin{haskellcode}
f :: Int -> Int -> Int
f :: (Int, Int) -> Int
\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:
\begin{haskellcode}
curry :: ((a, b) -> c) -> a -> b -> c
uncurry :: (a -> b -> c) -> (a, b) -> c
\end{haskellcode}

6
VL2_currying8.tex Normal file
View File

@ -0,0 +1,6 @@
So... now that we know what currying is, let's summarize:
\begin{itemizep}
\item 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 currying also allows us to do partial function application (which is important for function composition)
\end{itemizep}

17
VL2_define_functions1.tex Normal file
View File

@ -0,0 +1,17 @@
Now you know how a regular function looks like, e.g:
\begin{haskellcode}
f :: Int -> Int
f x = x + 1
\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 \code{static}.
\pause
\vspace{\baselineskip}
\\
Haskell allows us to \textbf{inline} functions in a few more ways, e.g.:
\begin{itemizep}
\item with \code{where}
\item with \code{let...in}
\item anonymously (lambda abstraction)
\end{itemizep}
\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.

View File

@ -0,0 +1,8 @@
We use \code{where} to define a helper function:
\begin{haskellcode}
f :: Int -> Int
f x = x + (y 2)
where
y :: Int -> Int
y p = x + p
\end{haskellcode}

View File

@ -0,0 +1,6 @@
Another way which is very similar would be using \code{let}:
\begin{haskellcode}
f :: Int -> Int
f x = let y p = x + p
in x + (y 2)
\end{haskellcode}

17
VL2_define_functions4.tex Normal file
View File

@ -0,0 +1,17 @@
These look almost the same, but they are different constructs. \code{where} is bound to the pattern matching \code{f x =} and may also have access to parts of a function that are not syntactically expressions, e.g.:
\begin{haskellcode}
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
\end{haskellcode}
While that is not possible with \code{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}
\\
There are a few more intricacies, but most of the time this is just style consideration:\\ \url{https://wiki.haskell.org/Let_vs._Where}
\pause
\vspace{\baselineskip}
\\
How would we have to rewrite the function in order to use \code{let}?

12
VL2_define_functions5.tex Normal file
View File

@ -0,0 +1,12 @@
We can also have \textbf{anonymous functions} which just means the function doesn't have a name:
\begin{haskellcode}
f :: Int -> Int
f x = (\y -> y + 1) x
\end{haskellcode}
\pause
Although this is basically the same as:
\begin{haskellcode}
f :: Int -> Int
f x = x + 1
\end{haskellcode}
Anonymous functions will come extremely handy later, you'll see.

147
VL2_handout.tex Normal file
View File

@ -0,0 +1,147 @@
\documentclass[12pt,a4paper,fleqn,oneside]{article}
% packages
\usepackage{xcolor}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage{listings}
\usepackage{minted}
% for \verb inside \item
\usepackage[T1]{fontenc}
\usepackage[Q=yes]{examplep}
% package configuration
\DeclareGraphicsExtensions{.pdf,.png,.jpg}
\usemintedstyle{friendly}
\newminted{haskell}{frame=single,numbers=left,samepage=true}
\newminted{cpp}{frame=single,numbers=left}
\newminted{c}{frame=single,numbers=left}
\renewcommand{\theFancyVerbLine}{\ttfamily
\textcolor[rgb]{0.0,0.0,0.0}{\footnotesize
\oldstylenums{\arabic{FancyVerbLine}}}}
% macros and environments
\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\pause}{}
\newcommand{\slidep}{}
\newenvironment{itemizep}
{\begin{itemize}}
{\end{itemize}}
% color definition
\definecolor{solarized}{HTML}{002B36}
\definecolor{mygreen}{rgb}{0,0.6,0}
\begin{document}
% title page information
\author{Julian Ospald}
\title{Haskell: higher order functions}
\maketitle
\tableofcontents
\section{Reiteration}
\input{VL2_reiteration.tex}
\section{Polymorphism}
\input{VL2_polymorphism1.tex}
\input{VL2_polymorphism2.tex}
\input{VL2_polymorphism3.tex}
\section{More ways to define functions}
\input{VL2_define_functions1.tex}
\subsection{Where}
\input{VL2_define_functions2.tex}
\subsection{Let}
\input{VL2_define_functions3.tex}
\subsection{Let vs Where}
\input{VL2_define_functions4.tex}
\subsection{Anonymous functions}
\input{VL2_define_functions5.tex}
\section{Currying}
\input{VL2_currying1.tex}
\\\\
\input{VL2_currying2.tex}
\\\\
\input{VL2_currying3.tex}
\\\\
\input{VL2_currying4.tex}
\\\\
\input{VL2_currying5.tex}
\\\\
\input{VL2_currying6.tex}
\input{VL2_currying7.tex}
\input{VL2_currying8.tex}
\section{Function composition}
\input{VL2_composition1.tex}
\input{VL2_composition2.tex}
\input{VL2_composition3.tex}
\section{Recursion patterns}
\input{VL2_rec_patterns1.tex}
\subsection{Map}
\input{VL2_rec_patterns2.tex}
\input{VL2_rec_patterns3.tex}
\\\\
\input{VL2_rec_patterns4.tex}
\\\\
\input{VL2_rec_patterns5.tex}
\subsection{Filter}
\input{VL2_rec_patterns6.tex}
\\\\
\input{VL2_rec_patterns7.tex}
\subsection{Fold}
\input{VL2_rec_patterns8.tex}
\input{VL2_rec_patterns9.tex}
\\\\
\input{VL2_rec_patterns10.tex}
\input{VL2_rec_patterns11.tex}
\subsection{Summary}
\input{VL2_rec_patterns12.tex}
\section{Reflection}
\subsection{What you should know}
\input{VL2_reflection1.tex}
\subsection{Questions for you}
\input{VL2_reflection2.tex}
\section{References}
\subsection{Links}
\input{VL_links.tex}
\subsection{Sources}
\input{VL_sources.tex}
\end{document}

20
VL2_polymorphism1.tex Normal file
View File

@ -0,0 +1,20 @@
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}
\\
\pause
Even better! Haskell supports polymorphism for both data types and functions.\\
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}

20
VL2_polymorphism2.tex Normal file
View File

@ -0,0 +1,20 @@
And now we are going to write functions to use it:
\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 \code{head} which gives us the first element of a list? The type signature actually looks like this:
\begin{haskellcode}
head :: [a] -> a
\end{haskellcode}
Makes sense?

0
VL2_polymorphism3.tex Normal file
View File

9
VL2_rec_patterns1.tex Normal file
View File

@ -0,0 +1,9 @@
Since we use lists a lot in haskell, we also want some more powerful functions to deal with them. E.g.:
\begin{itemize}
\item perform an operation on every element on a list
\item keep only some elements in the list, following some criteria
\item "summarize" the elements of the list somehow
\item ...
\end{itemize}
\pause
How do we do that?

14
VL2_rec_patterns10.tex Normal file
View File

@ -0,0 +1,14 @@
So how do our \code{sum}, \code{prod} and \code{length} functions look like if we use our \code{fold} abstraction?
\pause
\begin{haskellcode}
sum :: [Int] -> Int
sum xs = fold 0 (\x y -> x + y) xs
-- a Haskeller would write
sum = fold 0 (+)
prod :: [Int] -> Int
prod xs = fold 1 (\x y -> x * y) xs
length :: [a] -> Int
length xs = fold 0 (\x y -> 1 + y) xs
\end{haskellcode}

21
VL2_rec_patterns11.tex Normal file
View File

@ -0,0 +1,21 @@
There is also a function that folds from the \emph{left} which is also in the \emph{Prelude} and called \textbf{foldl}.\\
To summarize:
\begin{haskellcode}
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
\end{haskellcode}
For \code{foldl} the \code{z} is sort of the starting value.
\vspace{\baselineskip}
\\
\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/}
\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}
\vspace{\baselineskip}
\\
GHCi...
\begin{haskellcode}
> foldr (-) 0 [1, 2, 3]
> foldl (-) 0 [1, 2, 3]
\end{haskellcode}

5
VL2_rec_patterns12.tex Normal file
View File

@ -0,0 +1,5 @@
\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 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 although these functions are so fundamental that they are already implemented for most data types out there
\end{itemizep}

7
VL2_rec_patterns2.tex Normal file
View File

@ -0,0 +1,7 @@
Let's say we have a list of \code{Int} and want to add \code{2} to every element of the list.
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo ... ?
\end{haskellcode}
\pause
\textbf{Exercise:} Find the answer! 5 minutes time, remember the \emph{cons} operator \code{(:)}, pattern matching on lists and ofc recursion! Start with the case of an empty list.

23
VL2_rec_patterns3.tex Normal file
View File

@ -0,0 +1,23 @@
Solution?
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo [] = []
addTwo (x:xs) = (x + 2) : addTwo xs
\end{haskellcode}
\pause
Now we want to square every element:
\pause
\begin{haskellcode}
square :: [Int] -> [Int]
square [] = []
square (x:xs) = (x * x) : square xs
\end{haskellcode}
\pause
Now we want the absolute of every element:
\begin{haskellcode}
absList :: [Int] -> [Int]
absList [] = []
absList (x:xs) = (abs x) : absList xs
\end{haskellcode}
\pause
Do you notice something?

16
VL2_rec_patterns4.tex Normal file
View File

@ -0,0 +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.
\vspace{\baselineskip}
\\
\pause
I'll give you the type signature, can you guess how the implementation looks like?
\begin{haskellcode}
map :: (a -> b) -> [a] -> [b]
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
\end{haskellcode}
So we don't really know what the function \code{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.

15
VL2_rec_patterns5.tex Normal file
View File

@ -0,0 +1,15 @@
And now watch this:
\begin{haskellcode}
addTwo :: [Int] -> [Int]
addTwo xs = map (\x -> x + 2) xs
square :: [Int] -> [Int]
square xs = map (\x -> x * x) xs
absList :: [Int] -> [Int]
absList xs = map (\x -> abs x) xs
-- a haskeller would write, GHCi...
absList = map abs
\end{haskellcode}
\pause
Cool, right? So now we have abstracted out the \textbf{recursion pattern} that is all the same for those 3 functions. \code{map} is actually part of the standard library (called \emph{Prelude}).

23
VL2_rec_patterns6.tex Normal file
View File

@ -0,0 +1,23 @@
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}
filterEven :: [Int] -> [Int]
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
filterEven :: [Int] -> [Int]
filterEven [] = []
filterEven (x:xs)
| even x = x : filterEven xs
| otherwise = filterEven xs
\end{haskellcode}
\pause
Or: filter out all 0's, so we can count them later:
\begin{haskellcode}
filterZero :: [Int] -> [Int]
filterZero [] = []
filterZero (x:xs)
| x == 0 = x : filterZero xs
| otherwise = filterZero xs
\end{haskellcode}
Again: do you notice something?

14
VL2_rec_patterns7.tex Normal file
View File

@ -0,0 +1,14 @@
Let's abstract out the common pieces! This will be our type signature:
\begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a]
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
filter :: (a -> Bool) -> [a] -> [a]
filter f [] = []
filter f (x:xs)
| f x = x : filter f xs
| otherwise = filter f xs
\end{haskellcode}
Again: this function is part of the \emph{Prelude} as well.

25
VL2_rec_patterns8.tex Normal file
View File

@ -0,0 +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:
\begin{haskellcode}
sum :: [Int] -> Int
\end{haskellcode}
Solution?
\pause
\begin{haskellcode}
sum :: [Int] -> Int
sum [] = 0
sum (x:xs) = x + sum xs
\end{haskellcode}
\pause
Or the product:
\begin{haskellcode}
prod :: [Int] -> Int
prod [] = 1
prod (x:xs) = x * prod xs
\end{haskellcode}
\pause
Or the length:
\begin{haskellcode}
length :: [a] -> Int
length [] = 0
length (x:xs) = 1 + length xs
\end{haskellcode}

19
VL2_rec_patterns9.tex Normal file
View File

@ -0,0 +1,19 @@
To cut the story short, the abstract solution looks like this:
\begin{haskellcode}
fold :: b -> (a -> b -> b) -> [a] -> b
fold z f [] = z
fold z f (x:xs) = f x (fold z f xs)
\end{haskellcode}
Whoa! What's going on here?\\
Let's see...
\begin{itemizep}
\item \code{z} is what we return if the list is empty
\item \code{f} is our function (e.g. \code{(*)} or \code{(+)})
\item and the last remaining argument is the actual list we are working on
\end{itemizep}
\slidep
The function application has the following form:\\
\code{fold f z [a,b,c] == a `f` (b `f` (c `f` z))}
\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}.

7
VL2_reflection1.tex Normal file
View File

@ -0,0 +1,7 @@
\begin{itemize}
\item how to write polymorphic data types and functions
\item how you inline functions
\item what currying is and why we need it in haskell
\item how you compose functions
\item how to abstract out recursion patterns
\end{itemize}

9
VL2_reflection2.tex Normal file
View File

@ -0,0 +1,9 @@
\begin{itemize}
\item what is the difference between \code{let} and \code{where}?
\item what is the difference between \code{foldr} and \code{foldl}?
\item what is the difference between explicit and implicit recursion? Give examples
\item how many arguments does a haskell function have (strictly speaking)?
\item what do you have to keep in mind in order to make function composition work?
\item can you define map and filter in terms of foldr?
\item what is eta reduction (or: eta abstraction)?
\end{itemize}

6
VL2_reiteration.tex Normal file
View File

@ -0,0 +1,6 @@
\begin{itemize}
\item What is haskell? What are the 3 fundamental concepts behind it?
\item How do you do pattern matching?
\item What is the difference between lists and tuples? How do you construct them?
\item How do you define your own data types?
\end{itemize}