diff --git a/Notes.md b/Notes.md index 5131be2..2306c19 100644 --- a/Notes.md +++ b/Notes.md @@ -1,4 +1,12 @@ -# WTFunctional: Modifying your WTF-Count using functional programming # +Title: WTFunctional: Modifying yout WTF-Count using functional programming +Author: Oliver Rümpelein +html header: + + + + +# [%title] # ## Content ## @@ -8,24 +16,27 @@ + functions as first class “objects”: i.e. C++, 5; is a valid statement + lambdas + lists, maps, filters, folds - => readability, less code reproduction, threadsafety… + currying => just convenience - + code example: Pythagoraian triangles. + + code example: Pythagoraian triangles, bubble sort * Phuncy: The pythonic way is functional! - + Not strictly functional - + recursion, fafco - + lambda syntax - + map, fold => example (sum of squares?) + - Not strictly functional + - recursion, fafco + - lambda syntax + - map, fold => example (sum of squares?) - python lambda syntax: lambda a,b: a+b - fold with reduce - don't return lists, but iterators! - - Note: 2: map, filter, reduce - 3: map, filter, functools.reduce() - ```Removed reduce(). Use functools.reduce() if you really need it; - however, 99 percent of the time an explicit for loop is more - readable.``` - Why use it? => Multi-processing! - ``` + - Note: 2: map, filter, reduce, list comprehension + 3: map, filter, functools.reduce(), list comprehension + + + - The python2 to 3 page states: + “Removed `reduce()`. Use `functools.reduce()` if you really need it; + however, 99 percent of the time an explicit `for` loop is more + readable.” + - Why use it? => Multi-processing, WTF Count. + + ```python a = list(range(10)) b = 0 @@ -34,19 +45,20 @@ print(b) ``` vs. - ``` + + ```python from functools import reduce print(reduce(lambda x,y: x+y,map(lambda x: x**2,range(10)))) ``` - + currying: not really, but binding via lambdas or functools.partial() or + - currying: not really, but binding via lambdas or functools.partial() or https://mtomassoli.wordpress.com/2012/03/18/currying-in-python/ - + decorators! - + still FP, has advantages and is heavily used, i.e. in genomics (works on + - decorators! + - still FP has advantages and is heavily used, i.e. in genomics (works on tons of lengthy lists) * FunCtional++: On the fast lane - + "Classical" C++ has some functional stuff, bust i.e. no lambdas (hardly usable) - + Changed with the new C++11-standard - + Buzzwords: + - "Classical" C++ has some functional stuff, bust i.e. no lambdas (hardly usable) + - Changed with the new C++11-standard + - Buzzwords: - `map` defines a Datatype in C++! - lambdas in C++ ```[](int x, int y) { return a a +extract [] = error("Too few objects") +extract (x:xs) = x +a = extract [1,2,3,4,5] + +addto :: (Num a) => [a] -> a -> [a] +addto [] _ = [] -- edge case (list empty) +addto (x:xs) y = (x+y) : addto xs y +b = [1..4] +-- c == [5,6,7,8] +c = addto b 4 + +-- d == [25,36,49,64] +d = map (^2) c + +-- e == [6,8] +e = filter (\x -> (mod x 2) == 0) c + +mfold :: (t -> t1 -> t1) -> t1 -> [t] -> t1 +mfold f z [] = z +mfold f z (x:xs) = f x (mfold f z xs) +msum = mfold (+) 0 +g = msum [1..100] + +pt = [(a,b,c) | a <- [1..15], b <- [1..a], c <- [1..b], a^2 == b^2 + c^2] + +bsort :: (t -> t -> Bool) -> [t] -> [t] +bsort f [] = [] +bsort f (x:xs) = (bsort f a) ++ [x] ++ (bsort f b) + where a = [ y | y <- xs, not (f x y) ] + b = [ y | y <- xs, (f x y) ] + +mbsort = bsort (\x y -> (x < y)) +h = [1, 20, -10, 5] +i = mbsort h diff --git a/examples/01_haskell_recursion.hs b/examples/01_haskell_recursion.hs deleted file mode 100644 index a190518..0000000 --- a/examples/01_haskell_recursion.hs +++ /dev/null @@ -1,12 +0,0 @@ -extract :: [a] -> a -extract [] = error("Too few objects") -extract (x:xs) = x -a = extract [1,2,3,4,5] - -addto :: (Num a) => [a] -> a -> [a] -addto [] _ = [] -- edge case (list empty) -addto (x:xs) y = (x+y) : addto xs y -b = [1..4] --- c == [5,6,7,8] -c = addto b 4 - diff --git a/tex/wtf.bib b/tex/wtf.bib new file mode 100644 index 0000000..d954d72 --- /dev/null +++ b/tex/wtf.bib @@ -0,0 +1,5 @@ +@online{whichfold, +title={Foldr Foldl Foldl' - HaskellWiki}, +urldate={2016-04-21}, +url={https://wiki.haskell.org/Foldr_Foldl_Foldl%27}, +} \ No newline at end of file diff --git a/tex/wtfunctional.tex b/tex/wtfunctional.tex index 740b540..1a286ba 100644 --- a/tex/wtfunctional.tex +++ b/tex/wtfunctional.tex @@ -3,6 +3,8 @@ \usepackage{babel} \usepackage{csquotes} \usepackage{tabularx} +\usepackage[backend=biber, style=numeric,]{biblatex} +\bibliography{wtf} \usepackage{fontspec} \setsansfont{Fira Sans} @@ -97,37 +99,34 @@ \end{frame} \begin{frame}[fragile]{Syntax – Lists (1)} - Lists in Haskell can only hold data of one type. They are defined using - \haskellcmd{a = [1,2,3,4]} or similar. - - \pause - Furthermore, an automatic range can be obtained by using - \haskellcmd{b = [1..4]}, where the last number is inclusive. - - \pause - If possible, Haskell will try to inhibit the step automatically - \haskellcmd{c = [1,3..7]} yields \haskellcmd{[1,3,5,7]}. - - \pause - When leaving out the end specifier, a range can be infinite. In this case, - it's up to the programmer to constrain things. + \begin{itemize}[<+->] + \item Lists in Haskell can only hold data of one type. They are defined using + \haskellcmd{a = [1,2,3,4]} or similar. + \item An automatic range can be obtained by using \haskellcmd{b = [1..4]}, + where the last number is inclusive. + \item If possible, Haskell will try to inhibit the step + automatically. \haskellcmd{c = [1,3..7]} yields + \haskellcmd{[1,3,5,7]}. + \item When leaving out the end specifier, a range can be infinite. In this case, + it's up to the programmer to constrain things. + \end{itemize} \end{frame} \begin{frame}[fragile]{Syntax – Lists (2)} - Two arrays can be concatenated using the \haskellcmd{++} operator - \haskellcmd{[1,2,3] ++ [4..7]} - - Single objects get pushed to the front using \haskellcmd{:}: - \haskellcmd{1:[2..7]}. - - This can also be used vice versa to extract single values from lists - \begin{haskell} - extract (x:xs) = x - -- a = 1 - a = extract [1..5] - \end{haskell} + \begin{itemize}[<+->] + \item Two lists can be concatenated using the \haskellcmd{++} operator: + \haskellcmd{[1,2,3] ++ [4..7]} + \item Single objects get pushed to the front using + \enquote{\haskellcmd{:}}: \haskellcmd{1:[2..7]}. + \item This can also be used vice versa to extract single values from lists: + \begin{haskell} + extract (x:xs) = x + -- a = 1 + a = extract [1..5] + \end{haskell} + \end{itemize} \end{frame} - + \begin{frame}[fragile]{Syntax – Recursion} Example: Add a value to every entry in an array \begin{haskell} @@ -139,8 +138,83 @@ c = addto b 4 \end{haskell} \end{frame} + +\begin{frame}[fragile]{Lambdas} + \begin{itemize}[<+->] + \item By now: lambda-functions well known from other programming languages + \item Represent \enquote{anonymous} functions, i.e. locally defined functions + without associated name + \item Can simply be passed to algorithms, i.e. sort. + \item Syntax: \haskellcmd{\var1 var2 -> retval} + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Maps, Filters} + \begin{itemize}[<+->] + \item A \emph{Map} applies a function to all elements of a list: + \haskellcmd{map (^2) c}\quad (square the elements of c) + \item A \emph{Filter} does exactly that to a list: + \haskellcmd{filter (\x -> (mod x 2) == 0) c} \quad (even numbers in c, + filtering done using a lambda function) + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Folds (1)} + \begin{itemize}[<+->] + \item \emph{Folds} (or sometimes \emph{reductions}) create single values + using whole lists, i.e. sums over all elements + \item Often implemented using recursion + \item Need a function, an initialization value and a list + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Folds (2)} + \uncover<+-> Example: Self written Right fold and sum: + \begin{haskell} + mfold f z [] = z + mfold f z (x:xs) = f x (mfold f z xs) + msum = mfold (+) 0 + -- g == 5050 + g = msum [1..100] + \end{haskell} + \uncover<+->{Note that this gets pretty resource hungry with large + lists, better use left-folds for this (see~\cite{whichfold})} +\end{frame} + +\begin{frame}[fragile]{Example: Pythagorean triangles} + Get all Pythagorean triangles with a hypotenuse off length at most 15: + \begin{haskell} + > [(a,b,c) | a <- [1..15], + b <- [1..a], + c <- [1..b], + a^2 == b^2 + c^2] + [(5,4,3),(10,8,6),(13,12,5),(15,12,9)] + \end{haskell} +\end{frame} + +\begin{frame}[fragile]{Example: Bubble-sort} + Recursive, functional bubble-sort algorithm: + \begin{haskell} + bsort f [] = [] + bsort f (x:xs) = (bsort f a) ++ [x] ++ (bsort f b) + where a = [ y | y <- xs, not (f x y) ] + b = [ y | y <- xs, (f x y) ] + mbsort = bsort (\x y -> (x > y)) + \end{haskell} + \pause Result: + \begin{haskell} + λ> h = [1, 20, -10, 5] + λ> mbsort h + [-10,1,5,29] + \end{haskell} +\end{frame} + +\begin{frame}[plain]{References} + \printbibliography +\end{frame} \end{document} %%% Local Variables: %%% mode: latex +%%% ispell-dictionary: en %%% End: \ No newline at end of file