Add polymorphism section at the beginning
This commit is contained in:
parent
2f40fb9421
commit
db59997841
96
VL2.tex
96
VL2.tex
@ -59,10 +59,60 @@
|
|||||||
\end{itemize}
|
\end{itemize}
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\section{2. More ways to define functions}
|
\section{2. Polymorphism}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{2. More ways to define functions}
|
\frametitle{2. Polymorphism}
|
||||||
|
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}
|
||||||
|
\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 (\emph{not} the same). 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?
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{3. More ways to define functions}
|
||||||
|
|
||||||
|
\begin{frame}[fragile]
|
||||||
|
\frametitle{3. More ways to define functions}
|
||||||
Now you know how a regular function looks like, e.g:
|
Now you know how a regular function looks like, e.g:
|
||||||
\begin{haskellcode}
|
\begin{haskellcode}
|
||||||
f :: Int -> Int
|
f :: Int -> Int
|
||||||
@ -82,10 +132,10 @@ Haskell allows us to \textbf{inline} functions in a few more ways, e.g.:
|
|||||||
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.
|
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}
|
\end{frame}
|
||||||
|
|
||||||
\subsection{2.1. Where}
|
\subsection{3.1. Where}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{2.1. Where}
|
\frametitle{3.1. Where}
|
||||||
We use \code{where} to define a helper function:
|
We use \code{where} to define a helper function:
|
||||||
\begin{haskellcode}
|
\begin{haskellcode}
|
||||||
f :: Int -> Int
|
f :: Int -> Int
|
||||||
@ -95,10 +145,10 @@ f x = x + (y 2)
|
|||||||
\end{haskellcode}
|
\end{haskellcode}
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\subsection{2.2. Let}
|
\subsection{3.2. Let}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{2.2. Let}
|
\frametitle{3.2. Let}
|
||||||
Another way which is very similar would be using \code{let}:
|
Another way which is very similar would be using \code{let}:
|
||||||
\begin{haskellcode}
|
\begin{haskellcode}
|
||||||
f :: Int -> Int
|
f :: Int -> Int
|
||||||
@ -107,10 +157,10 @@ f x = let y p = x + p
|
|||||||
\end{haskellcode}
|
\end{haskellcode}
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\subsection{2.3. Let vs Where}
|
\subsection{3.3. Let vs Where}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{2.3. Let vs Where}
|
\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.:
|
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}
|
\begin{haskellcode}
|
||||||
f x
|
f x
|
||||||
@ -130,10 +180,10 @@ There are a few more intricacies, but most of the time this is just style consid
|
|||||||
How would we have to rewrite the function in order to use \code{let}?
|
How would we have to rewrite the function in order to use \code{let}?
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\subsection{2.4. Anonymous functions}
|
\subsection{3.4. Anonymous functions}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{2.4. Anonymous functions}
|
\frametitle{3.4. Anonymous functions}
|
||||||
We can also have \textbf{anonymous functions} which just means the function doesn't have a name:
|
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
|
||||||
@ -148,10 +198,10 @@ f x = x + 1
|
|||||||
Anonymous functions will come extremely handy later, you'll see.
|
Anonymous functions will come extremely handy later, you'll see.
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\section{3. Currying}
|
\section{4. Currying}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying}
|
\frametitle{4. 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:
|
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}
|
||||||
@ -168,7 +218,7 @@ which is actually pretty close.
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying (ctn.)}
|
\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.
|
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}
|
\vspace{\baselineskip}
|
||||||
\\
|
\\
|
||||||
@ -176,7 +226,7 @@ Let that sink in a little bit and read it again.
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying (ctn.)}
|
\frametitle{4. Currying (ctn.)}
|
||||||
Maybe a mathematical example will make things clearer. Let's say we have the function:\\
|
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}
|
||||||
@ -198,7 +248,7 @@ $g(3) = f (2, 3) = 3 / 2$
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying (ctn.)}
|
\frametitle{4. Currying (ctn.)}
|
||||||
You can also imagine this geometrically:\\
|
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)$ 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}
|
\vspace{\baselineskip}
|
||||||
@ -209,7 +259,7 @@ For every of these steps we can define a real new function. This scales up to an
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying (ctn.)}
|
\frametitle{4. Currying (ctn.)}
|
||||||
So in mathematical terms you can say:\\
|
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}
|
||||||
@ -229,7 +279,7 @@ On the other hand function application is \emph{left}-associative, so \code{f 3
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying (ctn.)}
|
\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:
|
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}
|
||||||
@ -254,7 +304,7 @@ f = \x -> (\y -> (\z -> ... )) -- right-associative, ofc
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{3. Currying (ctn.)}
|
\frametitle{4. Currying (ctn.)}
|
||||||
As said in the beginning of this section, these two look pretty similar:
|
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
|
||||||
@ -269,10 +319,10 @@ uncurry :: (a -> b -> c) -> (a, b) -> c
|
|||||||
\end{haskellcode}
|
\end{haskellcode}
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\section{4. Function composition}
|
\section{5. Function composition}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{4. Function composition}
|
\frametitle{5. 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.
|
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}
|
\vspace{\baselineskip}
|
||||||
\\
|
\\
|
||||||
@ -297,7 +347,7 @@ composedFunction = f . g
|
|||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{4. Function composition}
|
\frametitle{5. Function composition}
|
||||||
But let's not stop here. What does the dot \code{(.)} actually mean?
|
But let's not stop here. What does the dot \code{(.)} actually mean?
|
||||||
\vspace{\baselineskip}
|
\vspace{\baselineskip}
|
||||||
\\
|
\\
|
||||||
@ -318,10 +368,10 @@ Solution:
|
|||||||
\end{haskellcode}
|
\end{haskellcode}
|
||||||
\end{frame}
|
\end{frame}
|
||||||
|
|
||||||
\section{5. Recursion patterns}
|
\section{6. Recursion patterns}
|
||||||
|
|
||||||
\begin{frame}[fragile]
|
\begin{frame}[fragile]
|
||||||
\frametitle{5. Recursion patterns}
|
\frametitle{6. Recursion patterns}
|
||||||
Since we use lists a lot in haskell, we also want some more powerful functions to deal with them. E.g.:
|
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 perform an operation on every element on a list
|
||||||
|
Loading…
Reference in New Issue
Block a user