From d9590b00f73fc235c49e6ce4195d981630bcd483 Mon Sep 17 00:00:00 2001 From: Niklas Heim Date: Mon, 20 May 2024 19:59:26 +0200 Subject: [PATCH] Lecture 13 - Lecture notes (#30) --- .vitepress/config.mts | 1 + lectures/index.md | 9 +- lectures/lecture13.md | 349 ++++++++++++++++++++++++++++++++ lectures/lecture13/fold.png | Bin 0 -> 17266 bytes lectures/lecture13/fold.tex | 45 ++++ lectures/lecture13/foldlist.png | Bin 0 -> 8236 bytes lectures/lecture13/foldlist.tex | 28 +++ 7 files changed, 428 insertions(+), 4 deletions(-) create mode 100644 lectures/lecture13.md create mode 100644 lectures/lecture13/fold.png create mode 100644 lectures/lecture13/fold.tex create mode 100644 lectures/lecture13/foldlist.png create mode 100644 lectures/lecture13/foldlist.tex diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 8b48c2d..c27ef12 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -42,6 +42,7 @@ export default withMermaid( { text: '10: IO & Monads', link: '/lectures/lecture10'}, { text: '11: Monadic Parsing', link: '/lectures/lecture11'}, { text: '12: State Monad', link: '/lectures/lecture12'}, + { text: '13: Monoids & Foldables', link: '/lectures/lecture13'}, { text: '14: Parallel Programming', link: '/lectures/lecture14'}, ] }, diff --git a/lectures/index.md b/lectures/index.md index 9dfeedb..26ad996 100644 --- a/lectures/index.md +++ b/lectures/index.md @@ -95,16 +95,17 @@ We discuss some more examples of type classes, most importantly `Functor`s. [`State.hs`](https://github.com/aicenter/FUP/blob/main/code/State.hs). [`StateIO.hs`](https://github.com/aicenter/FUP/blob/main/code/StateIO.hs). -## Lecture 13: Monoids & Foldables - -Lecture notes coming soon! +## [Lecture 13](lecture13): Monoids & Foldables [Slides](https://github.com/aicenter/FUP/blob/main/lectures/lecture13.pdf). [Log](https://github.com/aicenter/FUP/blob/main/code/lecture13.hs). [Dataset](https://github.com/aicenter/FUP/blob/main/code/FUP-hw.csv). -## [Lecture 14](lecture14): Parallel Haskell +## [Bonus Lecture](lecture14): Parallel Haskell + +Introduces Haskell's spark system and demonstrates how to use `Strategy` types for simple +parallelization of existing Haskell programs. [`pfold.hs`](https://github.com/aicenter/FUP/blob/main/code/pfold.hs). [`parmaze.hs`](https://github.com/aicenter/FUP/blob/main/code/parmaze.hs). diff --git a/lectures/lecture13.md b/lectures/lecture13.md new file mode 100644 index 0000000..9c83449 --- /dev/null +++ b/lectures/lecture13.md @@ -0,0 +1,349 @@ +--- +outline: deep +--- +# Monoids & Foldables + +The _**fold**_ operation is one of (if not *the*) most important construction in functional +programming. An example we have seen very often already is using `foldr` to sum a list of numbers: + +```haskell +𝝺> sum = foldr (+) 0 +𝝺> sum [1,2,3] +6 +``` + +But there are many more things we can do with a fold! Another example is to define `and`: +```haskell +𝝺> and = foldr (&&) True +𝝺> and [True,True,True] +True + +𝝺> and [True,False] +False +``` +An perhaps a tiny bit more interesting, counting the number of a specific element in a list: +```haskell +𝝺> count e = foldr (\x acc -> if e==x then acc+1 else acc) 0 +𝝺> count 2 [1,2,1,2,2,3] +3 +``` +Arguably the most advanced example we have seen of a fold is the monadic fold of mazes in `setPath` +of [Lab 12](/labs/lab12#manipulations-with-maze). + +Importantly, we can implement a number of useful functions _**in terms of fold**_, so theoretically, +we don't need much more than a datastructure being foldable. For example: +```haskell +length = foldr (\_ -> (+1)) 0 +map f = foldr ((:) . f) [] +``` + +::: tip Fold: Aggregation & traversal +If we take a look at the type signature of `foldr` we see that it contains a `Foldable` type +constraint: +```haskell +foldr :: Foldable t => (b -> a -> b) -> b -> t a -> b +``` +In this lecture we will explore the essence of this `Foldable` typeclass and pick at the different +parts that make a fold. Conceptually, there are two parts to folding: +1. The _**aggregation**_ - represented by the function `b -> a -> b`. We will use an abstraction + called a [`Monoid`](#aggregation-semigroups-monoids) to treat this part of the fold separately. +2. The _**traversal**_ - which walks over the foldable datastructure `t a`. This is what the [`Foldable`](#traversal-foldables) typeclass is doing. +::: + +## Aggregation: Semigroups & Monoids + +Before we get to monoids which represent the aggregation part of a fold, we will define a semigroup. +A _**semigroup**_ is an algebra with a *domain* and a *binary, associative operation*. For example, +addition on the natural numbers forms a semigroup: The domain $\mathbb N$ with the operation $+$ +satisfies associativity: $a+(b+c) = (a+b)+c$. + +Formally, we define a *semigroup* $\langle S, \diamond\rangle$ as a set $S$ endowed with a +binary operation $\diamond$ that satisfies + +$$ a \diamond (b \diamond c) = (a \diamond b) \diamond c. $$ + +A _**monoid**_ $\langle M, \diamond, u \rangle$ is a semigroup with a *unit* $u \in M$ that satisfies + +$$ u \diamond a = a = a \diamond u. $$ + +In other words, a monoid has an identity element (e.g. for $+$ this element would be $0$). + +Some examples of monoids are: + +- $\langle \mathbb N, +, 0 \rangle$ - Addition of natural numbers +- $\langle \mathbb N, \times, 1 \rangle$ - Multiplication of natural numbers +- $\langle$ `[a]`, `++` , `[]` $\rangle$ - Lists and concatenation +- $\langle A^A, \circ, \text{id} \rangle$ - Selfmaps $f:A\rightarrow A$ form a monoid under + composition $\circ$. + +In Haskell, the typclass `Semigroup` defines an operation `<> :: a -> a -> a` (i.e. binary operation +that takes two elements of type `a` and produces another such element). +For lists we can implement semigroup simply with `++`: +```haskell +class Semigroup a where + (<>) :: a -> a -> a -- assumed to be associative + +-- list is a semigroup +instance Semigroup [] where + (<>) = (++) + +> [1,2,3] <> [4,5,6] +[1,2,3,4,5,6] +``` + +The `Monoid` typeclass adds the identity element `mempty`, which for the list monoid is of course +`[]`. +```haskell +class Semigroup a => Monoid a where + mempty :: a + + mconcat :: [a] -> a + mconcat = foldr (<>) mempty + + mappend :: a -> a -> a + mappend = (<>) + +instance Semigroup [] where + mempty = [] +``` + +For `Int`s we already noticed that we can have multiple monoids. To define a monoid over addition we +therefore need a new type +```haskell +newtype Sum a = Sum {getSum :: a} + +instance Num a => Semigroup (Sum a) where + (<>) = (+) + stimes n (Sum a) = Sum (fromIntegral n * a) + +instance Num a => Monoid (Sum a) where + mempty = Sum 0 + +𝝺> (Sum 7) <> (Sum 4) +Sum {getSum = 11} +``` + +::: tip *WHY?!* +Great question. Why should we jump through the hoops of *defining another type for addition*?! +1. *Abstraction*. Remember, monoids let us separate the aggregation part of a fold. This is useful + because we only need to define `<>` for a new type and we can immediately fold e.g. over lists, + trees, and anything that's foldable. +2. Semigroups give us *associativity*, which we can use to our advantage. For example, we can + evaluate large expressions of `<>` in *any order*. This means, for example, that we can execute + huge folds in a distributed fashion: + +Assume that `<>` is an operation that is much more expensive than a simple `+`, then we can execute +the first `(...)` on a different process/device and accumulate afterwards without having to worry +about correctness. +```haskell +(a <> b <> c) <> (d <> e <> f) +``` +::: + + +### Simple examples of monoids + +`Any` (resp. `All`) is the disjunctive (resp. conjunctive) monoid on `Bool`: + +```haskell +𝝺> (Any False) <> (Any True) <> (Any False) +Any {getAny = True} +``` + +For a monoid `m` its dual monoid is `Dual m` +```haskell +𝝺> (Dual "a") <> (Dual "b") <> (Dual "c") +Dual {getDual = "cba"} +``` + +Product of monoids: +```haskell +𝝺> (Sum 2,Product 3) <> (Sum 5,Product 7) +(Sum {getSum = 7},Product {getProduct = 21}) +``` + + +### Advanced examples of monoids +`Map` is a monoid under `union`: +```haskell +𝝺> Map.fromList [(1,"a")] <> Map.fromList [(1,"b")] <> Map.fromList [(2,"c")] +fromList [(1,"a"),(2,"c")] +``` +where `<> = Map.union` is a *left-biased* union of keys (meaning, the left-most argument with the +same key will override the ones further to the right). + +We could implement another monoid instance for `Map`, which instead of overwriting recurring keys, +accumulates the corresponding values. For this we need a new type we can call `MMap`: +```haskell +newtype MMap k v = MMap (Map.Map k v) + +fromList :: Ord k => [(k,v)] -> MMap k v +fromList xs = MMap (Map.fromList xs) + +instance (Ord k, Monoid v) => Semigroup (MMap k v) where + (MMap m1) <> (MMap m2) = MMap (Map.unionWith mappend m1 m2) +``` +By defining `<>` via the `unionWith` function and `mappend` (monoidal append) we can +accumulate any `MMap` that has values which are instances of `Monoid`: + +```haskell +𝝺> fromList [(1,"a")] <> fromList [(1,"b")] <> fromList [(2,"c")] +MMap ( + 1 : "ab" + 2 : "c" +) + +𝝺> fromList [('a', Sum 1)] <> fromList [('a',Sum 2)] <> fromList [('b',Sum 3)] +MMap ( + 'a' : Sum {getSum = 3} + 'b' : Sum {getSum = 3} +) +``` + + +## Traversal: Foldables + +With `Monoid` we have successfully abstracted away the aggregation part of folding operations. +Now we have to formalize how to traverse datastructures we want to fold. + +Let $M = \langle M, \diamond, u\rangle$ be a monoid, $f : A\rightarrow M$ a function that takes a +values of type $A$ to a monoid, and `lst = [a1, ... , an]` a list of elements from $A$. +The function `foldMap` of `lst` w.r.t. $M$ and $f$ is the composition of `map f` followed by the +aggregation $\diamond$. + +![](lecture13/foldlist.png){class="inverting-image"} + +To make something `Foldable`, we only have to implement `foldMap`: +```haskell +instance Foldable [] where + foldMap f = mconcat . fmap f +``` +And we will get a lot of functions for free (including `length`, `elem`, `maximum`, +etc.) + +```haskell +𝝺> :i Foldable +type Foldable :: (* -> *) -> Constraint +class Foldable t where + fold :: Monoid m => t m -> m + foldMap :: Monoid m => (a -> m) -> t a -> m + foldMap' :: Monoid m => (a -> m) -> t a -> m + foldr :: (a -> b -> b) -> b -> t a -> b + foldr' :: (a -> b -> b) -> b -> t a -> b + foldl :: (b -> a -> b) -> b -> t a -> b + foldl' :: (b -> a -> b) -> b -> t a -> b + foldr1 :: (a -> a -> a) -> t a -> a + foldl1 :: (a -> a -> a) -> t a -> a + toList :: t a -> [a] + null :: t a -> Bool + length :: t a -> Int + elem :: Eq a => a -> t a -> Bool + maximum :: Ord a => t a -> a + minimum :: Ord a => t a -> a + sum :: Num a => t a -> a + product :: Num a => t a -> a + {-# MINIMAL foldMap | foldr #-} + -- Defined in ‘Data.Foldable’ +instance Foldable (Either a) -- Defined in ‘Data.Foldable’ +instance Foldable [] -- Defined in ‘Data.Foldable’ +instance Foldable Maybe -- Defined in ‘Data.Foldable’ +instance Foldable Solo -- Defined in ‘Data.Foldable’ +instance Foldable ((,) a) -- Defined in ‘Data.Foldable’ +``` + +::: details `foldr` in terms of `foldMap` +For in depth information about `Foldable` implementations you can refer to the [Haskell +Wiki](https://en.wikibooks.org/wiki/Haskell/Foldable). Most importantly, it shows how to implement +`foldr` in terms of `foldMap` by exploiting the monoid of self-maps. +::: + + +For new types like `Tree a` we have to implement `foldMap` to inform Haskell about how to traverse +it. For a tree we can define +```haskell +data Tree a = Leaf a | Node (Tree a) (Tree a) + +instance Foldable Tree where + foldMap :: Monoid m => (a -> m) -> Tree a -> m + foldMap f (Leaf x) = f x + foldMap f (Node l r) = foldMap f l <> foldMap f r + +tree :: Tree Int +tree = Node (Leaf 7) (Node (Leaf 2) (Leaf 3)) + +𝝺> foldMap Sum tree +Sum {getSum = 12} +``` +which immediately lets us fold any `Tree m` where `Monoid m => Tree m`. + +![](lecture13/fold.png){class="inverting-image"} + +### Example: `MMap` statistics + +For `MMap`s we already have a monoid instance, so let's use it to compute some statistics. +With a simple `Count` monoid we can compute how many elements of a given value are in a list: +```haskell +instance Semigroup Count where + (Count n1) <> (Count n2) = Count (n1+n2) + +instance Monoid Count where + mempty = Count 0 + +count :: a -> Count +count _ = Count 1 + +singleton :: k -> v -> MMap k v +singleton k v = MMap (Map.singleton k v) + +𝝺> foldMap (\x -> singleton x (count x)) [1,2,3,3,2,4,5,5,5] +MMap ( + 1 : Count 1 + 2 : Count 2 + 3 : Count 2 + 4 : Count 1 + 5 : Count 3 +) +``` + +Perhaps more interestingly, we can use a product of monoids (i.e. a tuple of monoids) to compute +statistics over the first letter of a list of words: +```haskell +ws = words $ map toLower "Size matters not. Look at me. Judge me by my size, do you? Hmm? Hmm. And well you should not. For my ally is the Force, and a powerful ally it is. Life creates it, makes it grow. Its energy surrounds us and binds us. Luminous beings are we, not this crude matter. You must feel the Force around you; here, between you, me, the tree, the rock, everywhere, yes. Even between the land and the ship." +it :: [String] +``` + +We can define a function that collects a bunch of monoids which we want to fold over: +```haskell +stats :: Foldable t => t a -> (Count, Min Int, Max Int) +stats word = (count word, Min $ length word, Max $ length word) + +𝝺> stats "size" +(Count 1,Min 4,Max 4) +``` + +Each of the monoids above we want to again fold over `MMap`s with the first character as keys. +Effectively `MMap` is very similar to grouping, hence the name `groupBy`: +```haskell +groupBy :: (Ord k, Monoid m) => (a -> k) -> (a -> m) -> (a -> MMap k m) +groupBy keyf valuef a = singleton (keyf a) (valuef a) + +𝝺> groupBy head stats "size" +MMap ( + 's' : (Count 1,Min 4,Max 4) +) +``` + +Finally we just have to call `foldMap` to accumulate all the `stats`. +```haskell +𝝺> foldMap (groupBy head stats) ws +MMap ( + 'a' : (Count 10, Min 1, Max 6) + 'b' : (Count 5, Min 2, Max 7) + 'c' : (Count 2, Min 5, Max 7) + 'd' : (Count 1, Min 2, Max 2) + ... + 'w' : (Count 2, Min 3, Max 4) + 'y' : (Count 6, Min 3, Max 4) +) +``` + diff --git a/lectures/lecture13/fold.png b/lectures/lecture13/fold.png new file mode 100644 index 0000000000000000000000000000000000000000..77f86e319fc795ba402f58a312f842dba5e1f036 GIT binary patch literal 17266 zcma*O1ys~u^e;Muq#z-nFo=SrbPpgUFf;ojttaYH02kCnO<5g8D-~SSWI?=`@_|QVe~9Npum-WkV$*&~5v|nF%|UG8(Q
dBE)j$_~-7&?0$rGMPmd*48-gbaakY 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 Sy6pfNBqyybRVr!h|Gxkzav>xD literal 0 HcmV?d00001 diff --git a/lectures/lecture13/fold.tex b/lectures/lecture13/fold.tex new file mode 100644 index 0000000..fb45310 --- /dev/null +++ b/lectures/lecture13/fold.tex @@ -0,0 +1,45 @@ +\documentclass{standalone} +\usepackage{tikz} +\usetikzlibrary{arrows} +\usetikzlibrary{shapes.multipart} +\usetikzlibrary{shapes,snakes} +\usepackage[bitstream-charter]{mathdesign} + +\newcommand\irregularcircle[2]{% radius, irregularity +\pgfextra {\pgfmathsetmacro\len{(#1)+rand*(#2)}} ++(0:\len pt) +\foreach \a in {10,20,...,350}{ + \pgfextra {\pgfmathsetmacro\len{(#1)+rand*(#2)}} + -- +(\a:\len pt) +} -- cycle +} + + + +\begin{document} + \begin{tikzpicture}[xscale=1.2] + \scriptsize + \coordinate (c) at (3.5,2); + \draw[blue,rounded corners=1mm] (c) \irregularcircle{2cm}{1mm}; + + \foreach \x/\t/\k/\y in + {2.5/$a_1$/0/3,2.2/$a_2$/1/1.5,2.6/$a_3$/2/1.2,4/$a_{n-2}$/4/1.6,4.5/$a_{n-1}$/5/2,5/$a_n$/6/2.5} + \node (a\k) at (\x,\y) {\t}; + \foreach \x/\t/\k in {.5/$a_1$/0,1.5/$a_2$/1,2.5/$a_3$/2,3.5/$\cdots$/3,4.5/$a_{n-2}$/4,5.5/$a_{n-1}$/5,6.5/$a_n$/6} { + \node (f\k) at (\x,-1.5) {$f($\t$)$}; + } + \foreach \k in {0,1,2} + \draw[->] (a\k) -- (f\k); + \foreach \k in {4,5,6} + \draw[->] (a\k) -- (f\k); + + \foreach \x in {0,1,2,3,4,5,6} + \node at (\x,-1.5) {$\diamond$}; + + \node at (7,-1.5) {$=$}; + \node at (7.5,-1.5) {result}; + \node at (-0.3,-1.5) {$u$}; +\end{tikzpicture} +\end{document} + + diff --git a/lectures/lecture13/foldlist.png b/lectures/lecture13/foldlist.png new file mode 100644 index 0000000000000000000000000000000000000000..294cee1481b013ea2853f663132051e75ebd3aa7 GIT binary patch literal 8236 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 TJ)cO(Qnr`uFV>&`{>T3UB(E?H literal 0 HcmV?d00001 diff --git a/lectures/lecture13/foldlist.tex b/lectures/lecture13/foldlist.tex new file mode 100644 index 0000000..f4d4056 --- /dev/null +++ b/lectures/lecture13/foldlist.tex @@ -0,0 +1,28 @@ +\documentclass{standalone} +\usepackage{tikz} +\usetikzlibrary{arrows} +\usetikzlibrary{shapes.multipart} +\usetikzlibrary{shapes,snakes} +\usepackage[bitstream-charter]{mathdesign} + +\begin{document} +\begin{tikzpicture}[xscale=1.6] + \draw (0,0) grid (7,-1); + \foreach \x/\t/\k in {.5/$a_1$/0,1.5/$a_2$/1,2.5/$a_3$/2,3.5/$\cdots$/3,4.5/$a_{n-2}$/4,5.5/$a_{n-1}$/5,6.5/$a_n$/6} { + \node (a\k) at (\x,-0.5) {\t}; + \node (f\k) at (\x,-2) {$f($\t$)$}; + } + \foreach \k in {0,1,2} + \draw[->] (a\k) -- (f\k); + \foreach \k in {4,5,6} + \draw[->] (a\k) -- (f\k); + + \foreach \x in {0,1,2,3,4,5,6} + \node at (\x,-2) {$\diamond$}; + + \node at (7,-2) {$=$}; + \node at (7.5,-2) {result}; + \node at (-0.3,-2) {$u$}; +\end{tikzpicture} +\end{document} +