First draft of second lecture about higher order functions
This commit is contained in:
parent
ade43b77ae
commit
c4e7b6096b
352
VL2.tex
Normal file
352
VL2.tex
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
\documentclass[10pt,a5paper,mathserif,serif,usenames,dvipsnames]{beamer}
|
||||||
|
|
||||||
|
% packages
|
||||||
|
\usepackage{xcolor}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amsfonts}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{listings}
|
||||||
|
\usepackage{minted}
|
||||||
|
|
||||||
|
% for \verb inside \item
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage[Q=yes]{examplep}
|
||||||
|
|
||||||
|
% package configuration
|
||||||
|
\DeclareGraphicsExtensions{.pdf,.png,.jpg}
|
||||||
|
\beamertemplatenavigationsymbolsempty
|
||||||
|
\setbeamertemplate{footline}[frame number]
|
||||||
|
\usemintedstyle{friendly}
|
||||||
|
\newminted{haskell}{frame=single,numbers=left}
|
||||||
|
\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}}}}
|
||||||
|
|
||||||
|
% title page information
|
||||||
|
\author{Julian Ospald}
|
||||||
|
\institute{FH Bielefeld}
|
||||||
|
\title{Haskell: higher order functions}
|
||||||
|
|
||||||
|
% color definition
|
||||||
|
\definecolor{solarized}{HTML}{002B36}
|
||||||
|
\definecolor{mygreen}{rgb}{0,0.6,0}
|
||||||
|
|
||||||
|
% macros and environments
|
||||||
|
\newcommand{\code}[1]{\texttt{#1}}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\frame{\titlepage}
|
||||||
|
|
||||||
|
\begin{frame}[allowframebreaks=0.8]
|
||||||
|
\frametitle{Table of Contents}
|
||||||
|
\tableofcontents
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{1. Reiteration}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{1. Reiteration}
|
||||||
|
\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}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{2. More ways to define functions}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{2. More ways to define functions}
|
||||||
|
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.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{2.1. Where}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{2.1. Where}
|
||||||
|
We use \code{where} to define a helper function:
|
||||||
|
\begin{haskellcode}
|
||||||
|
f :: Int -> Int
|
||||||
|
f x = x + (y 2)
|
||||||
|
where
|
||||||
|
y p = x + p
|
||||||
|
\end{haskellcode}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{2.2. Let}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{2.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}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{2.3. Let vs Where}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{2.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}?
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{2.4. Anonymous functions}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{2.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.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{3. Currying}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. Currying}
|
||||||
|
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.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. 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.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. 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$
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. 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.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. 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?
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. 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}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. 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}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{4. Function composition}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{4. Function composition}
|
||||||
|
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}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{4. 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}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{5. Recursion patterns}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{5. Recursion patterns}
|
||||||
|
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? 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.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{5. Recursion patterns (ctn.)}
|
||||||
|
Solution?
|
||||||
|
\begin{haskellcode}
|
||||||
|
addTwo :: [Int] -> [Int]
|
||||||
|
addTwo [] = []
|
||||||
|
addTwo (x:xs) = (x + 2) : addTwo xs
|
||||||
|
\end{haskellcode}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\end{document}
|
Loading…
Reference in New Issue
Block a user