From fcbb846d7e28f0f30397de62665c52b47e161083 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Mon, 20 Apr 2015 00:32:01 +0200 Subject: [PATCH] VL1: Restructure files, add proper article/handout version --- VL1.tex | 531 ++++----------------------------------- VL1_handout.tex | 170 +++++++++++++ VL1_reflection1.tex | 7 + VL1_reflection2.tex | 18 ++ VL1_resume1.tex | 4 + VL1_resume2.tex | 20 ++ VL1_resume3.tex | 11 + VL1_think_haskell.tex | 18 ++ VL1_toolchain.tex | 8 + VL1_what_is_haskell1.tex | 5 + VL1_what_is_haskell2.tex | 13 + VL1_what_is_haskell3.tex | 5 + VL1_what_is_haskell4.tex | 19 ++ VL1_what_is_haskell5.tex | 7 + VL1_what_is_haskell6.tex | 4 + VL1_what_is_haskell7.tex | 9 + VL1_why_haskell1.tex | 15 ++ VL1_why_haskell2.tex | 23 ++ VL1_why_haskell3.tex | 13 + VL1_why_haskell4.tex | 7 + VL1_why_haskell5.tex | 12 + VL1_write_haskell1.tex | 21 ++ VL1_write_haskell10.tex | 11 + VL1_write_haskell11.tex | 20 ++ VL1_write_haskell12.tex | 7 + VL1_write_haskell13.tex | 22 ++ VL1_write_haskell14.tex | 7 + VL1_write_haskell15.tex | 23 ++ VL1_write_haskell16.tex | 13 + VL1_write_haskell17.tex | 7 + VL1_write_haskell2.tex | 9 + VL1_write_haskell3.tex | 21 ++ VL1_write_haskell4.tex | 13 + VL1_write_haskell5.tex | 11 + VL1_write_haskell6.tex | 22 ++ VL1_write_haskell7.tex | 19 ++ VL1_write_haskell8.tex | 15 ++ VL1_write_haskell9.tex | 19 ++ VL_links.tex | 8 + VL_sources.tex | 6 + 40 files changed, 704 insertions(+), 489 deletions(-) create mode 100644 VL1_handout.tex create mode 100644 VL1_reflection1.tex create mode 100644 VL1_reflection2.tex create mode 100644 VL1_resume1.tex create mode 100644 VL1_resume2.tex create mode 100644 VL1_resume3.tex create mode 100644 VL1_think_haskell.tex create mode 100644 VL1_toolchain.tex create mode 100644 VL1_what_is_haskell1.tex create mode 100644 VL1_what_is_haskell2.tex create mode 100644 VL1_what_is_haskell3.tex create mode 100644 VL1_what_is_haskell4.tex create mode 100644 VL1_what_is_haskell5.tex create mode 100644 VL1_what_is_haskell6.tex create mode 100644 VL1_what_is_haskell7.tex create mode 100644 VL1_why_haskell1.tex create mode 100644 VL1_why_haskell2.tex create mode 100644 VL1_why_haskell3.tex create mode 100644 VL1_why_haskell4.tex create mode 100644 VL1_why_haskell5.tex create mode 100644 VL1_write_haskell1.tex create mode 100644 VL1_write_haskell10.tex create mode 100644 VL1_write_haskell11.tex create mode 100644 VL1_write_haskell12.tex create mode 100644 VL1_write_haskell13.tex create mode 100644 VL1_write_haskell14.tex create mode 100644 VL1_write_haskell15.tex create mode 100644 VL1_write_haskell16.tex create mode 100644 VL1_write_haskell17.tex create mode 100644 VL1_write_haskell2.tex create mode 100644 VL1_write_haskell3.tex create mode 100644 VL1_write_haskell4.tex create mode 100644 VL1_write_haskell5.tex create mode 100644 VL1_write_haskell6.tex create mode 100644 VL1_write_haskell7.tex create mode 100644 VL1_write_haskell8.tex create mode 100644 VL1_write_haskell9.tex create mode 100644 VL_links.tex create mode 100644 VL_sources.tex diff --git a/VL1.tex b/VL1.tex index e66d3b0..393fc48 100644 --- a/VL1.tex +++ b/VL1.tex @@ -38,6 +38,10 @@ % macros and environments \newcommand{\code}[1]{\texttt{#1}} +\newcommand{\slidep}{\onslide<+->} +\newenvironment{itemizep} + {\begin{itemize}[<+->]} + {\end{itemize}} \begin{document} @@ -52,92 +56,27 @@ \begin{frame} \frametitle{1. Why haskell?} -A Haskeller might claim: haskell... -\begin{itemize}[<+->] -\item eliminates certain classes of bugs -\item not only disallows bad programs, but also defines what constitutes a bad program -\item makes it easy to reason about code -\item decreases the bus-factor -\item makes it possible to apply huge changes to large programs without worrying about the implicit state machine -\item makes it easier to program complex problems -\item allows for clean APIs, even without any OOP -\item a haskell program of 10K LOC isn't that much different to maintain as a 100K LOC -\item refactoring in haskell means abstraction -\end{itemize} -\vspace{\baselineskip} -\onslide<+-> -We'll have to see if this holds true. +\input{VL1_why_haskell1.tex} \end{frame} \begin{frame}[fragile] \frametitle{1. Why haskell? (ctn.)} -From C++ std: -\begin{cppcode} -void pop(); -\end{cppcode} -\onslide<+-> -From the C FLINT library: -\begin{ccode} -void fmpz_mod_poly_add( - fmpz_mod_poly_t res, - const fmpz_mod_poly_t poly1, - const fmpz_mod_poly_t poly2); -\end{ccode} -\vspace{\baselineskip} -\onslide<+-> -Regular C functions in real-world (omitting examples on purpose): -\begin{itemize}[<+->] -\item 100+ LOC -\item at least 7 ifs, 4 whiles, 12 variables, 1 goto -\item accesses both static and global variables -\item indenting level of 5 or more -\item a lot of memory management and custom-made error handling -\item references everywhere! -\end{itemize} +\input{VL1_why_haskell2.tex} \end{frame} \begin{frame} \frametitle{1. Why haskell? (ctn.)} -You need to change only one single line in such a C function. You have to know: -\begin{itemize}[<+->] -\item does the order of function calls matter? -\item how does the change effect the memory management? Do we have memory leaks? Do we access invalid memory? -\item does it change the state of static or global variables? -\item does it implicitly change the state of out-parameters? -\item if it changes any of those states, is the function still correct? -\item what happens if the program flow reaches this code-path with variable X in that particular state, while variable Z is NULL, and... -\item did you just nuke a small former Soviet state? -\end{itemize} -\vspace{\baselineskip} -\onslide<+-> -Conclusion: you really need to understand the complete environment of that line/function. +\input{VL1_why_haskell3.tex} \end{frame} \begin{frame} \frametitle{1. Why haskell? (ctn.)} -But java helps! Does it? -Sort of, because: -\begin{itemize}[<+->] -\item it improves APIs compared to C, since you can hide or encapsulate information in the state of an object -\item it has a garbage collector, so you don't need to worry too much about memory -\item an experienced programmer will find it easier to manage side-effects in Java, because you can e.g. have every impure functions throw an IO exception -\end{itemize} +\input{VL1_why_haskell4.tex} \end{frame} \begin{frame} \frametitle{1. Why haskell? (ctn.)} -Unfortunately, with java we: -\begin{itemize}[<+->] -\item now got even more states to keep track of (intellectual complexity?) -\item have clouded the program flow... it's now about object-interaction with their explicit and implicit states and because of the increase of indirection, it might get even harder to do actual abstraction -\item still have \textbf{side effects} everywhere: one object changes the state of another and vice versa, may arbitrarily write to the hard drive, do kernel calls or launch a missile -\end{itemize} -\onslide<+-> -Some parts of the implicit state machine have been made explicit by modelling classes, but it's still there and we have to deal with it, because we are modelling everything around states. Wouldn't it be nice if we could just forget about the global state machine? Maybe there is even a way to remove side effects and have more "predictability"? -\onslide<+-> -\vspace{\baselineskip} -\\ -We are lucky. There is. It's called \textbf{Haskell}. +\input{VL1_why_haskell5.tex} \end{frame} \section{2. What is haskell?} @@ -149,123 +88,54 @@ We are lucky. There is. It's called \textbf{Haskell}. \begin{frame} \frametitle{2. What is haskell? (ctn.)} -Haskell is a \textbf{functional}, \textbf{pure}, \textbf{lazy} and \textbf{statically typed} high-level programming language. -\vspace{\baselineskip} -\pause -\\ -A few of the following facts will be white lies. But let's not worry about that. It's maybe more about "how to think in terms of haskell?" than "what is haskell?". +\input{VL1_what_is_haskell1.tex} \end{frame} \subsection{2.1. What does functional mean?} \begin{frame} \frametitle{2.1. What does \textbf{functional} mean?} -Think of haskell functions as regular \emph{mathematical} functions. -\onslide<+-> -\vspace{\baselineskip} -\includegraphics*[scale=0.4]{function-machine.png} -\begin{itemize}[<+->] -\item does this function write to the hard drive? -\item does the output depend on anything else except the input (e.g. time, environment, ...)? -\end{itemize} -\onslide<+-> -\vspace{\baselineskip} -It's all about \emph{input} and \emph{output} of functions! And that's it. Nothing else to worry about. +\input{VL1_what_is_haskell2.tex} \end{frame} \begin{frame} \frametitle{2.1. What does \textbf{functional} mean? (ctn.)} -\begin{itemize}[<+->] -\item \emph{first-class} citizens: functions are values and can be used as such -\item a haskell program is what happens when \emph{expressions are evaluated}, it's not about executing instructions -\end{itemize} +\input{VL1_what_is_haskell3.tex} \end{frame} \subsection{2.2. What does pure mean?} \begin{frame} \frametitle{2.2. What does \textbf{pure} mean?} -\emph{Referential transparency}, as in: -\onslide<+-> -\begin{itemize}[<+->] -\item everything (variables, data structures...) is \emph{immutable} -\item expressions never have side-effects (remember: mathematical functions) -\item same input $\mapsto$ same output... \emph{always}! -\item replace a function with it's (return) value? Yes. What happens in C or java if you do that? Remember \code{void pop();}? -\end{itemize} -\onslide<+-> -\vspace{\baselineskip} -possible benefits? -\begin{itemize}[<+->] -\item parallelism -\item equational reasoning and refactoring -\item less bugs! -\end{itemize} -\onslide<+-> -\vspace{\baselineskip} -Question: call-by-value? call-by-reference? call-by-need? +\input{VL1_what_is_haskell4.tex} \end{frame} \subsection{2.3. What does lazy mean?} \begin{frame} \frametitle{2.3. What does \textbf{lazy} mean?} -In haskell expressions are not evaluated until their results are actually needed. That has a lot of consequences, a few of them being: -\onslide<+-> -\begin{itemize}[<+->] -\item infinite data structures are now possible (recursive and non-recursive) -\item defining new control structures by just defining a function (since not everything is evaluated... who needs if-then-else anyway?) -\item important for compositional programming and efficiency -\end{itemize} +\input{VL1_what_is_haskell5.tex} \end{frame} \subsection{2.4. What does statically typed mean?} \begin{frame} \frametitle{2.4. What does \textbf{statically typed} mean?} -Every haskell expression has a type and types are always checked at \emph{compile-time}. Programs with errors will not compile and definitely not run. -\vspace{\baselineskip} -\\ -It is possible to simulate dynamic types however, i.e. types which may be converted to the type you need them in, following rigid rules. In the end, they are still statically type-checked (as in: the compiler always knows what's going on). +\input{VL1_what_is_haskell6.tex} \end{frame} \subsection{2.5. Summary} \begin{frame} \frametitle{2.5. What is haskell again?} -Let's reiterate. Haskell is: -\begin{itemize} -\item functional -\item pure -\item lazy -\item statically typed (and truly type-safe) -\item even garbage collected -\item the world's finest imperative language (what??) -\end{itemize} +\input{VL1_what_is_haskell7.tex} \end{frame} \section{3. How to think haskell?} \begin{frame} \frametitle{3. How to think haskell?} -\begin{itemize}[<+->] -\item forget about imperative, procedural, OOP; forget about any programming language -\item think in types! -\begin{itemize}[<+->] -\item don't be afraid of type errors -\item let the type-checker do the work for you (does this function do what I think it does?) -\item understand functions just by looking at their type signature? -\end{itemize} -\item think abstract! -\begin{itemize}[<+->] -\item don't repeat yourself! -\item "develop a solution space, rather than an individual solution" -- Ralf Hinze -\item "imagine a graph, rather than a single path" -- Ralf Hinze -\item "first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones" -- Ralf Hinze -\end{itemize} -\item solve atomic parts of general problems and combine them into greater solutions -\item don't be afraid of recursion! -\end{itemize} +\input{VL1_think_haskell.tex} \end{frame} \section{4. How to write haskell?} @@ -279,340 +149,97 @@ Let's reiterate. Haskell is: \begin{frame}[fragile] \frametitle{4.1. Declarations} -Let's go! -\begin{haskellcode} -x :: Int -x = 3 - --- how about this? -x = 5 - --- Int vs Integer -n :: Integer -n = 12345678909876543219873409823349873498723498 - -d :: Double -d = 5.0 - -c :: Char -c = 'k' - -s :: String -s = "Hello, world?" -\end{haskellcode} +\input{VL1_write_haskell1.tex} \end{frame} \subsection{4.2. Arithmetic and co.} \begin{frame}[fragile] \frametitle{4.2. Arithmetic and co.} -GHCi: -\begin{haskellcode} -> 3 + 5 -> (3 :: Integer) + (5 :: Int) -> 6 * 5.0 -> "Hello" ++ " world" -> "Haskell" > "C++" -> True && False -\end{haskellcode} +\input{VL1_write_haskell2.tex} \end{frame} \subsection{4.3. Functions and control structures} \begin{frame}[fragile] \frametitle{4.3. Functions and control structures} -Let's make our first function. We want something like the following mathematical function\\ -$f(x) = x * x$ -\vspace{\baselineskip} -\\ -How could the haskell code look like? -\pause -Almost the same: -\begin{haskellcode} -f x = x * x -\end{haskellcode} -\vspace{\baselineskip} -GHCi... -\pause -\vspace{\baselineskip} -\\ -What is a possible type signature for this function? -\begin{haskellcode} -f :: Int -> Int -f x = x * x -\end{haskellcode} -So the function gets an Int and returns an Int. Don't get confused by "\verb|->|". Just think of it as a symbol for separating input and output. +\input{VL1_write_haskell3.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.3. Functions and control structures (ctn.)} -In haskell we often use \textbf{pattern matching}. That means we define a function multiple times, but e.g. for different values of its input arguments. Let's see: -\pause -\vspace{\baselineskip} -\begin{haskellcode} -isZero :: Int -> Bool -isZero 0 = True -isZero x = False -\end{haskellcode} -\vspace{\baselineskip} -So if we pass it 0, we get True. If we do not pass 0, we get False and the value we passed gets basically ignored. -\vspace{\baselineskip} -\\ -What might happen if we remove the second or the third line? What is a \textbf{partial function} and a \textbf{total function}? +\input{VL1_write_haskell4.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.3. Functions and control structures (ctn.)} -How about \emph{recursion}? Let's define the modulo of any \emph{Int} to \emph{2}. -\pause -\vspace{\baselineskip} -\begin{haskellcode} -mod2 :: Int -> Int -mod2 x - | x - 2 == 0 = 0 - | x - 2 < 0 = x - | otherwise = mod2 (x - 2) -\end{haskellcode} -These \verb#|# things above are called \textbf{guards} and are similar to \emph{pattern matching}. They are processed in order. If the condition on the left side of the equation is true, then it returns what stands on the right side of the equation. If it's false, then it processes the next line.\\ \code{otherwise} on the last line is just defined as \code{True}, to make these constructs easier to read and catch all other cases of input. +\input{VL1_write_haskell5.tex} \end{frame} \subsection{4.4. Lists} \begin{frame}[fragile] \frametitle{4.4. Lists} -The list is probably the most basic data structure in Haskell. Like the array in C. It is a singly-linked list and is very lazy. The compiler has numerous ways to optimize lists, so don't be afraid to use them, even for huge things. -\pause -We build lists by using either the \code{[]} notation: -\begin{haskellcode} -list1 :: [Integer] -list1 = [1, 2] -\end{haskellcode} -\pause -or by using the \emph{cons} operator \code{(:)} which takes an element and a list and produces a new list with the element prepended to the front. -\begin{haskellcode} -emptyList = [] - -list2 = 1 : [] - --- is this really a list? -list3 = [1, 2] == 1 : 2 : [] -\end{haskellcode} -\pause -How about something more interesting: -\begin{haskellcode} -infiniteList = [1..] -\end{haskellcode} +\input{VL1_write_haskell6.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.4. Lists (ctn.)} -Let's check on a few very common list operations: -\begin{haskellcode} -> [1, 2] ++ [4, 5] -- append two lists -> head [1, 2, 3] -- first element -> tail [1, 2, 3] -- everything after the head -> reverse [1, 2, 3] -- reverse a list -> take 2 [1, 2, 3] -- take the first two elements -> drop 2 [1, 2, 3] -- drop the first two elements -> sum [1, 2, 3] -> elem 7 [1, 2, 3] -- is there a 7 in the list? -\end{haskellcode} -\pause -A String in haskell is just a list of Chars! -\begin{haskellcode} -> ['a', 'b', 'c'] -> 'a' : [] -> head "abc" -> 'a' ++ 'c' -\end{haskellcode} +\input{VL1_write_haskell7.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.4. Lists (ctn.)} -Again, we can do pattern matching on lists. -\begin{haskellcode} -listLen :: [Integer] -> Integer -listLen [] = 0 -listLen (x:xs) = 1 + listLen xs -\end{haskellcode} -\pause -We can also nest pattern matching: -\begin{haskellcode} -sumEveryTwo :: [Integer] -> [Integer] -sumEveryTwo [] = 0 -sumEveryTwo (x:[]) = [x] -sumEveryTwo (x:(y:zs)) = (x + y) : sumEveryTwo zs -\end{haskellcode} -Note that \code{(x:(y:zs))} may also be written as \code{(x:y:zs)}. +\input{VL1_write_haskell8.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.4. Lists (ctn.)} -Haskell also supports \textbf{list comprehension} which is basically syntactic sugar for what we already know from maths.\\ -Let's define a set that contains the first ten even natural numbers:\\ -\pause -$S = \{2 \times x\ |\ x \in \mathbb{N},\ x \leq 10\}$ -\vspace{\baselineskip} -\pause -\\ -How does this look in haskell? -\pause -\begin{haskellcode} -> [x*2 | x <- [1..10]] -\end{haskellcode} -\pause -Now let's say we want all numbers between 50 and 100 that have the remainder 0 when divided by 12: -\pause -\begin{haskellcode} -> [x | x <- [50..100], mod x 12 == 0] -\end{haskellcode} -\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. +\input{VL1_write_haskell9.tex} \end{frame} \subsection{4.5. Pairs} \begin{frame}[fragile] \frametitle{4.5. Pairs} -Defining a pair is easy. -\begin{haskellcode} -p :: (Int, Char) -- this is the type -p = (2, 'y') -- this is how we construct the pair - --- pattern matching against pairs -sumPair :: (Int, Int) -> Int -sumPair (x, y) = x + y -\end{haskellcode} -\pause -Note: we use \code{(x, y)} notation for both the type and the definition! Those are still two different things. We can also have triples, quadruples etc. +\input{VL1_write_haskell10.tex} \end{frame} \subsection{4.6. Algebraic Data Types} \begin{frame}[fragile] \frametitle{4.6. 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: -\begin{haskellcode} -data WeekDay = Monday - | Tuesday - | Thursday - | Wednesday - | Friday - | Saturday - | Sunday -\end{haskellcode} -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 -\begin{haskellcode} -week :: [WeekDay] -week = [Monday, Tuesday, Thursday, Wednesday - , Friday, Saturday, Sunday] -\end{haskellcode} +\input{VL1_write_haskell11.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.6. 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 -\begin{haskellcode} -isMonday :: WeekDay -> Bool -isMonday Monday = True -isMonday x = False -\end{haskellcode} +\input{VL1_write_haskell12.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.6. 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 -\begin{haskellcode} -data MaybeInt = NoError Int - | Error String -\end{haskellcode} -\pause -So constructors are just \emph{functions}! And they can have arguments, just like functions. Let's check their types: -\begin{haskellcode} -> :t NoError -NoError :: Int -> MaybeInt -> :t Error -Error :: String -> MaybeInt -\end{haskellcode} -\pause -And now we can do sanity checks: -\begin{haskellcode} -calcSomething :: Int -> MaybeInt -calcSomething x - | x < 100 = NoError (x * 5) - | otherwise = Error "Int out of range!" -\end{haskellcode} +\input{VL1_write_haskell13.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.6. Algebraic Data Types (ctn.)} -And pattern match on it as well: -\begin{haskellcode} -addIntToList :: MaybeInt -> [Int] -addIntToList (NoError x) = [x] -addIntToList (Error str) = [] -\end{haskellcode} -So if we got an error, we just return an empty list, otherwise we return a list with the \code{Int} as its only element. +\input{VL1_write_haskell14.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.6. Algebraic Data Types (ctn.)} -Let's define something more complex. How about a tree? -\pause -\begin{haskellcode} -data Tree = Leaf Char - | Node Tree Int Tree -\end{haskellcode} -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. +\input{VL1_write_haskell15.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.6. Algebraic Data Types (ctn.)} -Let's build our tree: -\begin{haskellcode} -tree :: Tree -tree = Node - (Leaf 'x') - 1 - (Node - (Leaf 'y') - 2 - (Leaf 'z') - ) -\end{haskellcode} -See board... +\input{VL1_write_haskell16.tex} \end{frame} \begin{frame}[fragile] \frametitle{4.6. 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.: -\begin{haskellcode} -data AlgDataType = Constr1 Type11 Type12 - | Constr2 Type21 - | Constr3 Type31 Type32 Type33 - | Constr4 -\end{haskellcode} +\input{VL1_write_haskell17.tex} \end{frame} \section{5. Résumé} @@ -627,67 +254,28 @@ data AlgDataType = Constr1 Type11 Type12 \begin{frame} \frametitle{5.1. Questions so far?} -\begin{itemize} -\item How do functions with multiple parameters look like? -\item ... -\end{itemize} +\input{VL1_resume1.tex} \end{frame} \subsection{5.2. Common misconceptions} \begin{frame} \frametitle{5.2. Common misconceptions} -Now that we know the basics, let's clear up some common misconceptions about haskell. -\begin{itemize}[<+->] -\item haskell is only a language for university professors -\item haskell is not used in real world, see \url{https://wiki.haskell.org/Haskell_in_industry} -\begin{itemize} -\item Microsoft -\item NVIDIA -\item facebook -\item Google -\item Intel -\item AT\Q{&}T -\end{itemize} -\item you cannot model states in haskell -\item you cannot write larger programs in haskell -\item you cannot write useful programs in haskell -\item you cannot implement imperative algorithms -\item you cannot do concurrency, cryptography, web development, ... in haskell -\end{itemize} -\onslide<+-> -You can! +\input{VL1_resume2.tex} \end{frame} \subsection{5.3. Difficulties} \begin{frame} \frametitle{5.3. Difficulties} -Haskell is very powerful and can be used for pretty much anything. However, there are difficulties in any language. Let's name a few for haskell: -\begin{itemize}[<+->] -\item intellectual complexity? New way of thinking? -\item although you rarely need it in haskell, debugging can be difficult at times -\item because the type system is extremely powerful/complex, type error messages can be very confusing and don't always show the error you expected -\item no premium-like IDE with every possible feature (yet) -\item dynamic linking is sort of WIP yet, lots of ABI breakage -\item because most of the world thinks in imperative style languages, it's often difficult to find pseudo-code for functional style languages, so you end up reverse-engineering algorithms -\item some problems that are trivial in imperative languages, can be very difficult to solve in idiomatic haskell and vice versa -\item practical cryptography is possible, but a difficult topic in haskell, see \url{https://mail.haskell.org/pipermail/haskell-cafe/2015-February/118059.html} -\end{itemize} +\input{VL1_resume3.tex} \end{frame} \section{6. Toolchain} \begin{frame} \frametitle{6. Toolchain} -How to get started? You need: -\begin{itemize} -\item \textbf{GHC}: this is the Haskell compiler -\item \textbf{GHCi}: this an interactive environment of GHC, similar to the interactive ruby shell \emph{irb} -\item \textbf{The Haskell Platform}: a collection including GHC, GHCi and basic libraries -\end{itemize} -Go to \url{https://www.haskell.org/platform}\\ -For haskell IDEs, see \url{https://wiki.haskell.org/IDEs} +\input{VL1_toolchain.tex} \end{frame} \section{7. Reflection} @@ -700,37 +288,14 @@ For haskell IDEs, see \url{https://wiki.haskell.org/IDEs} \begin{frame} \frametitle{7.1. What you should know now} -\begin{itemize} -\item what haskell is -\item how you write haskell functions -\item how you handle lists and pairs -\item how you do pattern matching -\item how you create your own data types -\end{itemize} +\input{VL1_reflection1.tex} \end{frame} \subsection{7.2. Questions for you} \begin{frame}[fragile] \frametitle{7.2. Questions for you} -\begin{itemize} -\item What are side effects? -\item What is referential transparency? -\item Can you have referential transparency with side effects? -\item What does the output of a haskell function depend on? -\item What is laziness? -\item When are types checked in haskell? -\item What are the differences between lists and pairs? -\end{itemize} -\vspace{\baselineskip} -Does this compile? If not, fix it. Is this a total or a partial function? -\begin{haskellcode} -data IntOrDouble = MkDouble Double - | MkInt Int - -f :: Int -> IntOrDouble -f 0 = 0.5 -\end{haskellcode} +\input{VL1_reflection2.tex} \end{frame} \section{8. References} @@ -744,26 +309,14 @@ f 0 = 0.5 \begin{frame} \frametitle{8.1. Further reading and useful links} -\begin{itemize} -\item the most popular haskell course from Brent Yorgey:\\ \url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html} -\item very verbose and enthusiastic haskell book, good for reading once:\\ \url{http://learnyouahaskell.com} -\item collection of websites teaching haskell:\\ \url{https://github.com/bitemyapp/learnhaskell} -\item haskell programming tips (and wiki):\\ \url{https://wiki.haskell.org/Haskell_programming_tips} -\item the standard module (similar to libc in C):\\ \url{https://hackage.haskell.org/package/base-4.7.0.0/docs/Prelude.html} -\item debugging in haskell:\\ \url{https://wiki.haskell.org/Debugging} -\end{itemize} +\input{VL_links.tex} \end{frame} \subsection{8.2. Sources} \begin{frame} \frametitle{8.2. Sources} -\begin{itemize} -\item much content was borrowed or is based on the haskell course from Brent Yorgey:\\ \url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html} -\item a few small pieces from the LYAH book \url{http://learnyouahaskell.com} -\item general information from wikipedia: \\ \url{https://en.wikipedia.org} -\item general information from haskell wiki: \\ \url{https://wiki.haskell.org} -\end{itemize} +\input{VL_sources.tex} \end{frame} \end{document} \ No newline at end of file diff --git a/VL1_handout.tex b/VL1_handout.tex new file mode 100644 index 0000000..d620970 --- /dev/null +++ b/VL1_handout.tex @@ -0,0 +1,170 @@ +\documentclass[12pt,a4paper,fleqn,oneside]{article} + +% packages +\usepackage{xcolor} +\usepackage[utf8]{inputenc} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{graphicx} +\usepackage{hyperref} +\usepackage{listings} +\usepackage{minted} + +% for \verb inside \item +\usepackage[T1]{fontenc} +\usepackage[Q=yes]{examplep} + +% package configuration +\DeclareGraphicsExtensions{.pdf,.png,.jpg} +\usemintedstyle{friendly} +\newminted{haskell}{frame=single,numbers=left,samepage=true} +\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}}}} + +% macros and environments +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\pause}{} +\newcommand{\slidep}{} +\newenvironment{itemizep} + {\begin{itemize}} + {\end{itemize}} + +% color definition +\definecolor{solarized}{HTML}{002B36} +\definecolor{mygreen}{rgb}{0,0.6,0} + + +\begin{document} + +% title page information +\author{Julian Ospald} +\title{Haskell: introduction} + +\maketitle + +\tableofcontents + +\section{Why haskell?} + +\input{VL1_why_haskell1.tex} +\input{VL1_why_haskell2.tex} +\input{VL1_why_haskell3.tex} +\\\\ +\input{VL1_why_haskell4.tex} +\input{VL1_why_haskell5.tex} + + +\section{What is haskell?} + +\input{VL1_what_is_haskell1.tex} + +\subsection{What does functional mean?} + +\input{VL1_what_is_haskell2.tex} +\\\\ +\input{VL1_what_is_haskell3.tex} + +\subsection{What does pure mean?} +\input{VL1_what_is_haskell4.tex} + +\subsection{What does lazy mean?} +\input{VL1_what_is_haskell5.tex} + +\subsection{What does statically typed mean?} +\input{VL1_what_is_haskell6.tex} + +\subsection{Summary} +\input{VL1_what_is_haskell7.tex} + + +\section{How to think haskell?} + +\input{VL1_think_haskell.tex} + + +\section{How to write haskell?} + +\subsection{Declarations} +\input{VL1_write_haskell1.tex} + +\subsection{Arithmetic and co.} +\input{VL1_write_haskell2.tex} + +\subsection{Functions and control structures} +\input{VL1_write_haskell3.tex} +\input{VL1_write_haskell4.tex} +\input{VL1_write_haskell5.tex} + +\subsection{Lists} +\input{VL1_write_haskell6.tex} +\input{VL1_write_haskell7.tex} +\input{VL1_write_haskell8.tex} +\\\\ +\input{VL1_write_haskell9.tex} + +\subsection{Pairs} +\input{VL1_write_haskell10.tex} + +\subsection{Algebraic Data Types} +\input{VL1_write_haskell11.tex} +\input{VL1_write_haskell12.tex} +\input{VL1_write_haskell13.tex} +\input{VL1_write_haskell14.tex} +\\\\ +\input{VL1_write_haskell15.tex} +\\\\ +\input{VL1_write_haskell16.tex} +\\\\ +\input{VL1_write_haskell17.tex} + + +\section{Résumé} + +\subsection{Questions so far?} +\input{VL1_resume1.tex} + +\subsection{Common misconceptions} +\input{VL1_resume2.tex} + +\subsection{Difficulties} +\input{VL1_resume3.tex} + + +\section{Toolchain} +\input{VL1_toolchain.tex} + + +\section{Reflection} + +\subsection{What you should know} +\input{VL1_reflection1.tex} + +\subsection{Questions for you} +\input{VL1_reflection2.tex} + + +\section{References} + +\subsection{Links} +\input{VL_links.tex} + +\subsection{Sources} +\input{VL_sources.tex} + +\end{document} + + + + + + + + + + + + diff --git a/VL1_reflection1.tex b/VL1_reflection1.tex new file mode 100644 index 0000000..6507584 --- /dev/null +++ b/VL1_reflection1.tex @@ -0,0 +1,7 @@ +\begin{itemize} +\item what haskell is +\item how you write haskell functions +\item how you handle lists and pairs +\item how you do pattern matching +\item how you create your own data types +\end{itemize} \ No newline at end of file diff --git a/VL1_reflection2.tex b/VL1_reflection2.tex new file mode 100644 index 0000000..e84b48b --- /dev/null +++ b/VL1_reflection2.tex @@ -0,0 +1,18 @@ +\begin{itemize} +\item What are side effects? +\item What is referential transparency? +\item Can you have referential transparency with side effects? +\item What does the output of a haskell function depend on? +\item What is laziness? +\item When are types checked in haskell? +\item What are the differences between lists and pairs? +\end{itemize} +\vspace{\baselineskip} +Does this compile? If not, fix it. Is this a total or a partial function? +\begin{haskellcode} +data IntOrDouble = MkDouble Double + | MkInt Int + +f :: Int -> IntOrDouble +f 0 = 0.5 +\end{haskellcode} \ No newline at end of file diff --git a/VL1_resume1.tex b/VL1_resume1.tex new file mode 100644 index 0000000..225a9c3 --- /dev/null +++ b/VL1_resume1.tex @@ -0,0 +1,4 @@ +\begin{itemize} +\item How do functions with multiple parameters look like? +\item ... +\end{itemize} \ No newline at end of file diff --git a/VL1_resume2.tex b/VL1_resume2.tex new file mode 100644 index 0000000..ab5f3b3 --- /dev/null +++ b/VL1_resume2.tex @@ -0,0 +1,20 @@ +Now that we know the basics, let's clear up some common misconceptions about haskell. +\begin{itemizep} +\item haskell is only a language for university professors +\item haskell is not used in real world, see \url{https://wiki.haskell.org/Haskell_in_industry} +\begin{itemize} +\item Microsoft +\item NVIDIA +\item facebook +\item Google +\item Intel +\item AT\Q{&}T +\end{itemize} +\item you cannot model states in haskell +\item you cannot write larger programs in haskell +\item you cannot write useful programs in haskell +\item you cannot implement imperative algorithms +\item you cannot do concurrency, cryptography, web development, ... in haskell +\end{itemizep} +\slidep +You can! \ No newline at end of file diff --git a/VL1_resume3.tex b/VL1_resume3.tex new file mode 100644 index 0000000..8e4adcc --- /dev/null +++ b/VL1_resume3.tex @@ -0,0 +1,11 @@ +Haskell is very powerful and can be used for pretty much anything. However, there are difficulties in any language. Let's name a few for haskell: +\begin{itemizep} +\item intellectual complexity? New way of thinking? +\item although you rarely need it in haskell, debugging can be difficult at times +\item because the type system is extremely powerful/complex, type error messages can be very confusing and don't always show the error you expected +\item no premium-like IDE with every possible feature (yet) +\item dynamic linking is sort of WIP yet, lots of ABI breakage +\item because most of the world thinks in imperative style languages, it's often difficult to find pseudo-code for functional style languages, so you end up reverse-engineering algorithms +\item some problems that are trivial in imperative languages, can be very difficult to solve in idiomatic haskell and vice versa +\item practical cryptography is possible, but a difficult topic in haskell, see \url{https://mail.haskell.org/pipermail/haskell-cafe/2015-February/118059.html} +\end{itemizep} \ No newline at end of file diff --git a/VL1_think_haskell.tex b/VL1_think_haskell.tex new file mode 100644 index 0000000..ffd6d97 --- /dev/null +++ b/VL1_think_haskell.tex @@ -0,0 +1,18 @@ +\begin{itemizep} +\item forget about imperative, procedural, OOP; forget about any programming language +\item think in types! +\begin{itemizep} +\item don't be afraid of type errors +\item let the type-checker do the work for you (does this function do what I think it does?) +\item understand functions just by looking at their type signature? +\end{itemizep} +\item think abstract! +\begin{itemizep} +\item don't repeat yourself! +\item "develop a solution space, rather than an individual solution" -- Ralf Hinze +\item "imagine a graph, rather than a single path" -- Ralf Hinze +\item "first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones" -- Ralf Hinze +\end{itemizep} +\item solve atomic parts of general problems and combine them into greater solutions +\item don't be afraid of recursion! +\end{itemizep} \ No newline at end of file diff --git a/VL1_toolchain.tex b/VL1_toolchain.tex new file mode 100644 index 0000000..646685c --- /dev/null +++ b/VL1_toolchain.tex @@ -0,0 +1,8 @@ +How to get started? You need: +\begin{itemize} +\item \textbf{GHC}: this is the Haskell compiler +\item \textbf{GHCi}: this an interactive environment of GHC, similar to the interactive ruby shell \emph{irb} +\item \textbf{The Haskell Platform}: a collection including GHC, GHCi and basic libraries +\end{itemize} +Go to \url{https://www.haskell.org/platform}\\ +For haskell IDEs, see \url{https://wiki.haskell.org/IDEs} \ No newline at end of file diff --git a/VL1_what_is_haskell1.tex b/VL1_what_is_haskell1.tex new file mode 100644 index 0000000..9c83d41 --- /dev/null +++ b/VL1_what_is_haskell1.tex @@ -0,0 +1,5 @@ +Haskell is a \textbf{functional}, \textbf{pure}, \textbf{lazy} and \textbf{statically typed} high-level programming language. +\vspace{\baselineskip} +\pause +\\ +A few of the following facts will be white lies. But let's not worry about that. It's maybe more about "how to think in terms of haskell?" than "what is haskell?". \ No newline at end of file diff --git a/VL1_what_is_haskell2.tex b/VL1_what_is_haskell2.tex new file mode 100644 index 0000000..bee4d32 --- /dev/null +++ b/VL1_what_is_haskell2.tex @@ -0,0 +1,13 @@ +Think of haskell functions as regular \emph{mathematical} functions. +\slidep +\vspace{\baselineskip} +\begin{center} +\includegraphics*[scale=0.6]{function-machine.png} +\end{center} +\begin{itemizep} +\item does this function write to the hard drive? +\item does the output depend on anything else except the input (e.g. time, environment, ...)? +\end{itemizep} +\slidep +\vspace{\baselineskip} +It's all about \emph{input} and \emph{output} of functions! And that's it. Nothing else to worry about. \ No newline at end of file diff --git a/VL1_what_is_haskell3.tex b/VL1_what_is_haskell3.tex new file mode 100644 index 0000000..712adaa --- /dev/null +++ b/VL1_what_is_haskell3.tex @@ -0,0 +1,5 @@ +So, functional means: +\begin{itemizep} +\item \emph{first-class} citizens: functions are values and can be used as such +\item a haskell program is what happens when \emph{expressions are evaluated}, it's not about executing instructions +\end{itemizep} \ No newline at end of file diff --git a/VL1_what_is_haskell4.tex b/VL1_what_is_haskell4.tex new file mode 100644 index 0000000..8d35ade --- /dev/null +++ b/VL1_what_is_haskell4.tex @@ -0,0 +1,19 @@ +\emph{Referential transparency}, as in: +\slidep +\begin{itemizep} +\item everything (variables, data structures...) is \emph{immutable} +\item expressions never have side-effects (remember: mathematical functions) +\item same input $\mapsto$ same output... \emph{always}! +\item replace a function with it's (return) value? Yes. What happens in C or java if you do that? Remember \code{void pop();}? +\end{itemizep} +\slidep +\vspace{\baselineskip} +possible benefits? +\begin{itemizep} +\item parallelism +\item equational reasoning and refactoring +\item less bugs! +\end{itemizep} +\slidep +\vspace{\baselineskip} +Question: call-by-value? call-by-reference? call-by-need? \ No newline at end of file diff --git a/VL1_what_is_haskell5.tex b/VL1_what_is_haskell5.tex new file mode 100644 index 0000000..6254128 --- /dev/null +++ b/VL1_what_is_haskell5.tex @@ -0,0 +1,7 @@ +In haskell expressions are not evaluated until their results are actually needed. That has a lot of consequences, a few of them being: +\slidep +\begin{itemizep} +\item infinite data structures are now possible (recursive and non-recursive) +\item defining new control structures by just defining a function (since not everything is evaluated... who needs if-then-else anyway?) +\item important for compositional programming and efficiency +\end{itemizep} \ No newline at end of file diff --git a/VL1_what_is_haskell6.tex b/VL1_what_is_haskell6.tex new file mode 100644 index 0000000..8525934 --- /dev/null +++ b/VL1_what_is_haskell6.tex @@ -0,0 +1,4 @@ +Every haskell expression has a type and types are always checked at \emph{compile-time}. Programs with errors will not compile and definitely not run. +\vspace{\baselineskip} +\\ +It is possible to simulate dynamic types however, i.e. types which may be converted to the type you need them in, following rigid rules. In the end, they are still statically type-checked (as in: the compiler always knows what's going on). \ No newline at end of file diff --git a/VL1_what_is_haskell7.tex b/VL1_what_is_haskell7.tex new file mode 100644 index 0000000..d1dc46f --- /dev/null +++ b/VL1_what_is_haskell7.tex @@ -0,0 +1,9 @@ +Let's reiterate. Haskell is: +\begin{itemize} +\item functional +\item pure +\item lazy +\item statically typed (and truly type-safe) +\item even garbage collected +\item the world's finest imperative language (what??) +\end{itemize} \ No newline at end of file diff --git a/VL1_why_haskell1.tex b/VL1_why_haskell1.tex new file mode 100644 index 0000000..1c7d747 --- /dev/null +++ b/VL1_why_haskell1.tex @@ -0,0 +1,15 @@ +A Haskeller might claim: haskell... +\begin{itemizep} +\item eliminates certain classes of bugs +\item not only disallows bad programs, but also defines what constitutes a bad program +\item makes it easy to reason about code +\item decreases the bus-factor +\item makes it possible to apply huge changes to large programs without worrying about the implicit state machine +\item makes it easier to program complex problems +\item allows for clean APIs, even without any OOP +\item a haskell program of 10K LOC isn't that much different to maintain as a 100K LOC +\item refactoring in haskell means abstraction +\end{itemizep} +\vspace{\baselineskip} +\slidep +We'll have to see if this holds true. \ No newline at end of file diff --git a/VL1_why_haskell2.tex b/VL1_why_haskell2.tex new file mode 100644 index 0000000..58062d2 --- /dev/null +++ b/VL1_why_haskell2.tex @@ -0,0 +1,23 @@ +From C++ std: +\begin{cppcode} +void pop(); +\end{cppcode} +\slidep +From the C FLINT library: +\begin{ccode} +void fmpz_mod_poly_add( + fmpz_mod_poly_t res, + const fmpz_mod_poly_t poly1, + const fmpz_mod_poly_t poly2); +\end{ccode} +\vspace{\baselineskip} +\slidep +Regular C functions in real-world (omitting examples on purpose): +\begin{itemizep} +\item 100+ LOC +\item at least 7 ifs, 4 whiles, 12 variables, 1 goto +\item accesses both static and global variables +\item indenting level of 5 or more +\item a lot of memory management and custom-made error handling +\item references everywhere! +\end{itemizep} \ No newline at end of file diff --git a/VL1_why_haskell3.tex b/VL1_why_haskell3.tex new file mode 100644 index 0000000..23abff6 --- /dev/null +++ b/VL1_why_haskell3.tex @@ -0,0 +1,13 @@ +You need to change only one single line in such a C function. You have to know: +\begin{itemizep} +\item does the order of function calls matter? +\item how does the change effect the memory management? Do we have memory leaks? Do we access invalid memory? +\item does it change the state of static or global variables? +\item does it implicitly change the state of out-parameters? +\item if it changes any of those states, is the function still correct? +\item what happens if the program flow reaches this code-path with variable X in that particular state, while variable Z is NULL, and... +\item did you just nuke a small former Soviet state? +\end{itemizep} +\vspace{\baselineskip} +\slidep +Conclusion: you really need to understand the complete environment of that line/function. \ No newline at end of file diff --git a/VL1_why_haskell4.tex b/VL1_why_haskell4.tex new file mode 100644 index 0000000..40255ba --- /dev/null +++ b/VL1_why_haskell4.tex @@ -0,0 +1,7 @@ +But java helps! Does it? +Sort of, because: +\begin{itemizep} +\item it improves APIs compared to C, since you can hide or encapsulate information in the state of an object +\item it has a garbage collector, so you don't need to worry too much about memory +\item an experienced programmer will find it easier to manage side-effects in Java, because you can e.g. have every impure functions throw an IO exception +\end{itemizep} \ No newline at end of file diff --git a/VL1_why_haskell5.tex b/VL1_why_haskell5.tex new file mode 100644 index 0000000..6ba347c --- /dev/null +++ b/VL1_why_haskell5.tex @@ -0,0 +1,12 @@ +Unfortunately, with java we: +\begin{itemizep} +\item now got even more states to keep track of (intellectual complexity?) +\item have clouded the program flow... it's now about object-interaction with their explicit and implicit states and because of the increase of indirection, it might get even harder to do actual abstraction +\item still have \textbf{side effects} everywhere: one object changes the state of another and vice versa, may arbitrarily write to the hard drive, do kernel calls or launch a missile +\end{itemizep} +\slidep +Some parts of the implicit state machine have been made explicit by modelling classes, but it's still there and we have to deal with it, because we are modelling everything around states. Wouldn't it be nice if we could just forget about the global state machine? Maybe there is even a way to remove side effects and have more "predictability"? +\slidep +\vspace{\baselineskip} +\\ +We are lucky. There is. It's called \textbf{Haskell}. \ No newline at end of file diff --git a/VL1_write_haskell1.tex b/VL1_write_haskell1.tex new file mode 100644 index 0000000..5070e18 --- /dev/null +++ b/VL1_write_haskell1.tex @@ -0,0 +1,21 @@ +Let's go! +\begin{haskellcode} +x :: Int +x = 3 + +-- how about this? +x = 5 + +-- Int vs Integer +n :: Integer +n = 12345678909876543219873409823349873498723498 + +d :: Double +d = 5.0 + +c :: Char +c = 'k' + +s :: String +s = "Hello, world?" +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell10.tex b/VL1_write_haskell10.tex new file mode 100644 index 0000000..4a2b39d --- /dev/null +++ b/VL1_write_haskell10.tex @@ -0,0 +1,11 @@ +Defining a pair is easy. +\begin{haskellcode} +p :: (Int, Char) -- this is the type +p = (2, 'y') -- this is how we construct the pair + +-- pattern matching against pairs +sumPair :: (Int, Int) -> Int +sumPair (x, y) = x + y +\end{haskellcode} +\pause +Note: we use \code{(x, y)} notation for both the type and the definition! Those are still two different things. We can also have triples, quadruples etc. \ No newline at end of file diff --git a/VL1_write_haskell11.tex b/VL1_write_haskell11.tex new file mode 100644 index 0000000..e4e52ad --- /dev/null +++ b/VL1_write_haskell11.tex @@ -0,0 +1,20 @@ +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: +\begin{haskellcode} +data WeekDay = Monday + | Tuesday + | Thursday + | Wednesday + | Friday + | Saturday + | Sunday +\end{haskellcode} +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 +\begin{haskellcode} +week :: [WeekDay] +week = [Monday, Tuesday, Thursday, Wednesday + , Friday, Saturday, Sunday] +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell12.tex b/VL1_write_haskell12.tex new file mode 100644 index 0000000..7b3c865 --- /dev/null +++ b/VL1_write_haskell12.tex @@ -0,0 +1,7 @@ +And we can again \emph{pattern match} on our \code{WeekDay} type. Let's find out if a given day is a Monday: +\pause +\begin{haskellcode} +isMonday :: WeekDay -> Bool +isMonday Monday = True +isMonday x = False +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell13.tex b/VL1_write_haskell13.tex new file mode 100644 index 0000000..f923cd7 --- /dev/null +++ b/VL1_write_haskell13.tex @@ -0,0 +1,22 @@ +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 +\begin{haskellcode} +data MaybeInt = NoError Int + | Error String +\end{haskellcode} +\pause +So constructors are just \emph{functions}! And they can have arguments, just like functions. Let's check their types: +\begin{haskellcode} +> :t NoError +NoError :: Int -> MaybeInt +> :t Error +Error :: String -> MaybeInt +\end{haskellcode} +\pause +And now we can do sanity checks: +\begin{haskellcode} +calcSomething :: Int -> MaybeInt +calcSomething x + | x < 100 = NoError (x * 5) + | otherwise = Error "Int out of range!" +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell14.tex b/VL1_write_haskell14.tex new file mode 100644 index 0000000..97eaa19 --- /dev/null +++ b/VL1_write_haskell14.tex @@ -0,0 +1,7 @@ +And pattern match on it as well: +\begin{haskellcode} +addIntToList :: MaybeInt -> [Int] +addIntToList (NoError x) = [x] +addIntToList (Error str) = [] +\end{haskellcode} +So if we got an error, we just return an empty list, otherwise we return a list with the \code{Int} as its only element. \ No newline at end of file diff --git a/VL1_write_haskell15.tex b/VL1_write_haskell15.tex new file mode 100644 index 0000000..dc4aaf6 --- /dev/null +++ b/VL1_write_haskell15.tex @@ -0,0 +1,23 @@ +Let's define something more complex. How about a tree? +\pause +\begin{haskellcode} +data Tree = Leaf Char + | Node Tree Int Tree +\end{haskellcode} +Uh... that looks mean. Let's examine this.\\ +\pause +We have: +\begin{itemizep} +\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{itemizep} +\item \code{Tree} +\item \code{Int} +\item \code{Tree} +\end{itemizep} +\end{itemizep} +\slidep +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. \ No newline at end of file diff --git a/VL1_write_haskell16.tex b/VL1_write_haskell16.tex new file mode 100644 index 0000000..25c7120 --- /dev/null +++ b/VL1_write_haskell16.tex @@ -0,0 +1,13 @@ +Let's build our tree: +\begin{haskellcode} +tree :: Tree +tree = Node + (Leaf 'x') + 1 + (Node + (Leaf 'y') + 2 + (Leaf 'z') + ) +\end{haskellcode} +See board... \ No newline at end of file diff --git a/VL1_write_haskell17.tex b/VL1_write_haskell17.tex new file mode 100644 index 0000000..ff5e8d3 --- /dev/null +++ b/VL1_write_haskell17.tex @@ -0,0 +1,7 @@ +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.: +\begin{haskellcode} +data AlgDataType = Constr1 Type11 Type12 + | Constr2 Type21 + | Constr3 Type31 Type32 Type33 + | Constr4 +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell2.tex b/VL1_write_haskell2.tex new file mode 100644 index 0000000..85aa16f --- /dev/null +++ b/VL1_write_haskell2.tex @@ -0,0 +1,9 @@ +GHCi: +\begin{haskellcode} +> 3 + 5 +> (3 :: Integer) + (5 :: Int) +> 6 * 5.0 +> "Hello" ++ " world" +> "Haskell" > "C++" +> True && False +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell3.tex b/VL1_write_haskell3.tex new file mode 100644 index 0000000..92a77e1 --- /dev/null +++ b/VL1_write_haskell3.tex @@ -0,0 +1,21 @@ +Let's make our first function. We want something like the following mathematical function\\ +$f(x) = x * x$ +\vspace{\baselineskip} +\\ +How could the haskell code look like? +\pause +Almost the same: +\begin{haskellcode} +f x = x * x +\end{haskellcode} +\vspace{\baselineskip} +GHCi... +\pause +\vspace{\baselineskip} +\\ +What is a possible type signature for this function? +\begin{haskellcode} +f :: Int -> Int +f x = x * x +\end{haskellcode} +So the function gets an Int and returns an Int. Don't get confused by "\verb|->|". Just think of it as a symbol for separating input and output. \ No newline at end of file diff --git a/VL1_write_haskell4.tex b/VL1_write_haskell4.tex new file mode 100644 index 0000000..0fedc29 --- /dev/null +++ b/VL1_write_haskell4.tex @@ -0,0 +1,13 @@ +In haskell we often use \textbf{pattern matching}. That means we define a function multiple times, but e.g. for different values of its input arguments. Let's see: +\pause +\vspace{\baselineskip} +\begin{haskellcode} +isZero :: Int -> Bool +isZero 0 = True +isZero x = False +\end{haskellcode} +\vspace{\baselineskip} +So if we pass it 0, we get True. If we do not pass 0, we get False and the value we passed gets basically ignored. +\vspace{\baselineskip} +\\ +What might happen if we remove the second or the third line? What is a \textbf{partial function} and a \textbf{total function}? \ No newline at end of file diff --git a/VL1_write_haskell5.tex b/VL1_write_haskell5.tex new file mode 100644 index 0000000..261aee4 --- /dev/null +++ b/VL1_write_haskell5.tex @@ -0,0 +1,11 @@ +How about \emph{recursion}? Let's define the modulo of any \emph{Int} to \emph{2}. +\pause +\vspace{\baselineskip} +\begin{haskellcode} +mod2 :: Int -> Int +mod2 x + | x - 2 == 0 = 0 + | x - 2 < 0 = x + | otherwise = mod2 (x - 2) +\end{haskellcode} +These \verb#|# things above are called \textbf{guards} and are similar to \emph{pattern matching}. They are processed in order. If the condition on the left side of the equation is true, then it returns what stands on the right side of the equation. If it's false, then it processes the next line.\\ \code{otherwise} on the last line is just defined as \code{True}, to make these constructs easier to read and catch all other cases of input. \ No newline at end of file diff --git a/VL1_write_haskell6.tex b/VL1_write_haskell6.tex new file mode 100644 index 0000000..edea818 --- /dev/null +++ b/VL1_write_haskell6.tex @@ -0,0 +1,22 @@ +The list is probably the most basic data structure in Haskell. Like the array in C. It is a singly-linked list and is very lazy. The compiler has numerous ways to optimize lists, so don't be afraid to use them, even for huge things. +\pause +We build lists by using either the \code{[]} notation: +\begin{haskellcode} +list1 :: [Integer] +list1 = [1, 2] +\end{haskellcode} +\pause +or by using the \emph{cons} operator \code{(:)} which takes an element and a list and produces a new list with the element prepended to the front. +\begin{haskellcode} +emptyList = [] + +list2 = 1 : [] + +-- is this really a list? +list3 = [1, 2] == 1 : 2 : [] +\end{haskellcode} +\pause +How about something more interesting: +\begin{haskellcode} +infiniteList = [1..] +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell7.tex b/VL1_write_haskell7.tex new file mode 100644 index 0000000..8b29b4a --- /dev/null +++ b/VL1_write_haskell7.tex @@ -0,0 +1,19 @@ +Let's check on a few very common list operations: +\begin{haskellcode} +> [1, 2] ++ [4, 5] -- append two lists +> head [1, 2, 3] -- first element +> tail [1, 2, 3] -- everything after the head +> reverse [1, 2, 3] -- reverse a list +> take 2 [1, 2, 3] -- take the first two elements +> drop 2 [1, 2, 3] -- drop the first two elements +> sum [1, 2, 3] +> elem 7 [1, 2, 3] -- is there a 7 in the list? +\end{haskellcode} +\pause +A String in haskell is just a list of Chars! +\begin{haskellcode} +> ['a', 'b', 'c'] +> 'a' : [] +> head "abc" +> 'a' ++ 'c' +\end{haskellcode} \ No newline at end of file diff --git a/VL1_write_haskell8.tex b/VL1_write_haskell8.tex new file mode 100644 index 0000000..294b28d --- /dev/null +++ b/VL1_write_haskell8.tex @@ -0,0 +1,15 @@ +Again, we can do pattern matching on lists. +\begin{haskellcode} +listLen :: [Integer] -> Integer +listLen [] = 0 +listLen (x:xs) = 1 + listLen xs +\end{haskellcode} +\pause +We can also nest pattern matching: +\begin{haskellcode} +sumEveryTwo :: [Integer] -> [Integer] +sumEveryTwo [] = 0 +sumEveryTwo (x:[]) = [x] +sumEveryTwo (x:(y:zs)) = (x + y) : sumEveryTwo zs +\end{haskellcode} +Note that \code{(x:(y:zs))} may also be written as \code{(x:y:zs)}. \ No newline at end of file diff --git a/VL1_write_haskell9.tex b/VL1_write_haskell9.tex new file mode 100644 index 0000000..748d525 --- /dev/null +++ b/VL1_write_haskell9.tex @@ -0,0 +1,19 @@ +Haskell also supports \textbf{list comprehension} which is basically syntactic sugar for what we already know from maths.\\ +Let's define a set that contains the first ten even natural numbers:\\ +\pause +$S = \{2 \times x\ |\ x \in \mathbb{N},\ x \leq 10\}$ +\vspace{\baselineskip} +\pause +\\ +How does this look in haskell? +\pause +\begin{haskellcode} +> [x*2 | x <- [1..10]] +\end{haskellcode} +\pause +Now let's say we want all numbers between 50 and 100 that have the remainder 0 when divided by 12: +\pause +\begin{haskellcode} +> [x | x <- [50..100], mod x 12 == 0] +\end{haskellcode} +\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. \ No newline at end of file diff --git a/VL_links.tex b/VL_links.tex new file mode 100644 index 0000000..d2e80e2 --- /dev/null +++ b/VL_links.tex @@ -0,0 +1,8 @@ +\begin{itemize} +\item the most popular haskell course from Brent Yorgey:\\ \url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html} +\item very verbose and enthusiastic haskell book, good for reading once:\\ \url{http://learnyouahaskell.com} +\item collection of websites teaching haskell:\\ \url{https://github.com/bitemyapp/learnhaskell} +\item haskell programming tips (and wiki):\\ \url{https://wiki.haskell.org/Haskell_programming_tips} +\item the standard module (similar to libc in C):\\ \url{https://hackage.haskell.org/package/base-4.7.0.0/docs/Prelude.html} +\item debugging in haskell:\\ \url{https://wiki.haskell.org/Debugging} +\end{itemize} \ No newline at end of file diff --git a/VL_sources.tex b/VL_sources.tex new file mode 100644 index 0000000..a59cdfd --- /dev/null +++ b/VL_sources.tex @@ -0,0 +1,6 @@ +\begin{itemize} +\item much content was borrowed or is based on the haskell course from Brent Yorgey:\\ \url{https://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html} +\item a few small pieces from the LYAH book \url{http://learnyouahaskell.com} +\item general information from wikipedia: \\ \url{https://en.wikipedia.org} +\item general information from haskell wiki: \\ \url{https://wiki.haskell.org} +\end{itemize} \ No newline at end of file