|
|
@@ -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} |