|
|
@@ -436,6 +436,131 @@ Now let's say we want all numbers between 50 and 100 that have the remainder 0 w |
|
|
|
\code{x <- [50..100]} is the binding, while \code{mod x 12 == 0} is the predicate, separated by a comma. We can have multiple predicates. |
|
|
|
\end{frame} |
|
|
|
|
|
|
|
\begin{frame}[fragile] |
|
|
|
\frametitle{Algebraic Data Types} |
|
|
|
Of course we can also define our own data types in haskell. One very common type is the \emph{enumeration}. For example, we could define a data type for the Week: |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
data WeekDay = Monday |
|
|
|
| Tuesday |
|
|
|
| Thursday |
|
|
|
| Wednsday |
|
|
|
| Friday |
|
|
|
| Saturday |
|
|
|
| Sunday |
|
|
|
\end{lstlisting} |
|
|
|
This declares the new data type \code{WeekDay} with 7 \emph{constructors}. That means \code{Monday}, \code{Tuesday} etc. are all values of the type \code{WeekDay}. |
|
|
|
\pause |
|
|
|
\\ |
|
|
|
We could now define a whole week, by creating a list: |
|
|
|
\pause |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
week :: [WeekDay] |
|
|
|
week = [Monday, Tuesday, Thursday, Wednsday |
|
|
|
, Friday, Saturday, Sunday] |
|
|
|
\end{lstlisting} |
|
|
|
\end{frame} |
|
|
|
|
|
|
|
\begin{frame}[fragile] |
|
|
|
\frametitle{Algebraic Data Types (ctn.)} |
|
|
|
And we can again \emph{pattern match} on our \code{WeekDay} type. Let's find out if a given day is a monday: |
|
|
|
\pause |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
isMonday :: WeekDay -> Bool |
|
|
|
isMonday Monday = True |
|
|
|
isMonday x = False |
|
|
|
\end{lstlisting} |
|
|
|
\end{frame} |
|
|
|
|
|
|
|
\begin{frame}[fragile] |
|
|
|
\frametitle{Algebraic Data Types (ctn.)} |
|
|
|
But we can do more than enumerations. How about we do some error handling? Let's say we want a function to return an \code{Int}, but in case something went horribly wrong, we don't just want to return a 0 or some magic number, but a proper error message. Here we go: |
|
|
|
\pause |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
data MaybeInt = NoError Int |
|
|
|
| Error String |
|
|
|
\end{lstlisting} |
|
|
|
\pause |
|
|
|
And now we can do sanity checks: |
|
|
|
\pause |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
calcSomething :: Int -> MaybeInt |
|
|
|
calcSomething x |
|
|
|
| x < 100 = NoError (x * 5) |
|
|
|
| otherwise = Error "Int out of range!" |
|
|
|
\end{lstlisting} |
|
|
|
\pause |
|
|
|
So constructors are just \emph{functions}! And they can have arguments, just like functions. Let's check their types: |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
> :t NoError |
|
|
|
NoError :: Int -> MaybeInt |
|
|
|
> :t Error |
|
|
|
Error :: String -> MaybeInt |
|
|
|
\end{lstlisting} |
|
|
|
\end{frame} |
|
|
|
|
|
|
|
\begin{frame}[fragile] |
|
|
|
\frametitle{Algebraic Data Types (ctn.)} |
|
|
|
Let's define something more complex. How about a tree? |
|
|
|
\pause |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
data Tree = Leaf Char |
|
|
|
| Node Tree Int Tree |
|
|
|
\end{lstlisting} |
|
|
|
Uh... that looks mean. Let's examine this.\\ |
|
|
|
\pause |
|
|
|
We have: |
|
|
|
\begin{itemize}[<+->] |
|
|
|
\item defined a data type \code{Tree} |
|
|
|
\item a constructor \code{Leaf} of type \code{Tree} with one arguments of type \code{Char} |
|
|
|
\item a constructor \code{Node} of type \code{Tree} with 3 arguments |
|
|
|
\begin{itemize}[<+->] |
|
|
|
\item \code{Tree} |
|
|
|
\item \code{Int} |
|
|
|
\item \code{Tree} |
|
|
|
\end{itemize} |
|
|
|
\end{itemize} |
|
|
|
\onslide<+-> |
|
|
|
That means: a \code{Tree} can either be a \code{Leaf} or an internal \code{Node} with two sub-trees. If we want to create a \code{Leaf}, we have to pass the constructor a \code{Char}. If we want to create a \code{Node}, we have to pass 3 arguments, in order: another \code{Tree}, an \code{Int} and yet another \code{Tree}.\\ |
|
|
|
So we can save information in the leafs (\code{Char}) and in the internal nodes (\code{Int}).\\ |
|
|
|
This is just an example. There are endless more ways of trees. |
|
|
|
\end{frame} |
|
|
|
|
|
|
|
\begin{frame}[fragile] |
|
|
|
\frametitle{Algebraic Data Types (ctn.)} |
|
|
|
Let's build our tree: |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
tree :: Tree |
|
|
|
tree = Node |
|
|
|
(Leaf 'x') |
|
|
|
1 |
|
|
|
(Node |
|
|
|
(Leaf 'y') |
|
|
|
2 |
|
|
|
(Leaf 'z') |
|
|
|
) |
|
|
|
\end{lstlisting} |
|
|
|
See board... |
|
|
|
\end{frame} |
|
|
|
|
|
|
|
\begin{frame}[fragile] |
|
|
|
\frametitle{Algebraic Data Types (ctn.)} |
|
|
|
So if we want to generalize it, an algebraic data type has one or more \textbf{constructors}, and each of them can have zero or more arguments. E.g.: |
|
|
|
\setHaskellCodeStyle |
|
|
|
\begin{lstlisting} |
|
|
|
data AlgDataType = Constr1 Type11 Type12 |
|
|
|
| Constr2 Type21 |
|
|
|
| Constr3 Type31 Type32 Type33 |
|
|
|
| Constr4 |
|
|
|
\end{lstlisting} |
|
|
|
\end{frame} |
|
|
|
\begin{frame} |
|
|
|
\frametitle{Toolchain} |
|
|
|
You need: |
|
|
|