Browse Source

First draft of second lecture about higher order functions

stripped-german
Julian Ospald 9 years ago
parent
commit
c4e7b6096b
No known key found for this signature in database GPG Key ID: 220CD1C5BDEED020
1 changed files with 352 additions and 0 deletions
  1. +352
    -0
      VL2.tex

+ 352
- 0
VL2.tex View 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…
Cancel
Save