Philip Schwarz
August 08, 2021
34

Left and Right Folds - Comparison of a mathematical definition and a programmatic one - Polyglot FP for Fun and Profit - Haskell andย Scala

We compare typical definitions of the left and right fold functions, with their mathematical definitions in Sergei Winitzkiโs upcoming book: The Science of Functional Programming.

Errata:
Slide 13: "The way ๐๐๐๐๐ does it is by associating to the right" - should, of course, end in "to the left".

August 08, 2021

Transcript

1. Based on definitions from Left and Right Folds Comparison of

a mathematical definition and a programmatic one Polyglot FP for Fun and Profit - Haskell and Scala @philip_schwarz slides by https://www.slideshare.net/pjschwarz Sergei Winitzki sergei-winitzki-11a6431 Richard Bird http://www.cs.ox.ac.uk/people/richard.bird/
2. ๐๐๐๐๐ โท ๐ฝ โ ๐ผ โ ๐ฝ โ ๐ฝ โ

๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ โถ ๐ฅ๐  = ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ ๐ฅ๐  ๐๐๐๐๐ โท ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ โถ ๐ฅ๐  = ๐ ๐ฅ ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  If I have to write down the definitions of a left fold and a right fold for lists, here is what I write While both definitions are recursive, the left fold is tail recursive, whereas the right fold isnโt. Although I am very familiar with the above definitions, and view them as doing a good job of explaining the two folds, I am always interested in alternative ways of explaining things, and so I have been looking at Sergei Winitzkiโs mathematical definitions of left and right folds, in his upcoming book: The Science of Functional Programming (SOFP). Sergeiโs definitions of the folds are in the top two rows of the following table Sergei Winitzki Richard Bird @philip_schwarz
3. test1 = TestCase (assertEqual "foldl(+) 0 []" 0 (foldl (+)

0 [])) test2 = TestCase (assertEqual "foldl(+) 0 [1,2,3,4]" 10 (foldl (+) 0 [1,2,3,4])) test3 = TestCase (assertEqual "foldr (+) 0 []" 0 (foldr (+) 0 [])) test4 = TestCase (assertEqual "foldr (+) 0 [1,2,3,4]" 10 (foldr (+) 0 [1,2,3,4])) Left folds and right folds do not necessarily produce the same results. According to the first duality theorem of folding, one case in which the results are the same, is when we fold using the unit and associative operation of a monoid. First duality theorem. Suppose โ is associative with unit ๐. Then ๐๐๐๐๐ โ ๐ ๐ฅ๐  = ๐๐๐๐๐ โ ๐ ๐ฅ๐  For all finite lists ๐ฅ๐ . test5 = TestCase (assertEqual "foldl(-) 0 []" 0 (foldl (+) 0 [])) test6 = TestCase (assertEqual "foldl(-) 0 [1,2,3,4]" (- 10) (foldl (-) 0 [1,2,3,4])) test7 = TestCase (assertEqual "foldr (-) 0 []" 0 (foldr (-) 0 [])) test8 = TestCase (assertEqual "foldr (-) 0 [1,2,3,4]" (- 2) (foldr (-) 0 [1,2,3,4])) Folding integers left and right using the (Int,+,0) monoid, for example, produces the same results. But folding integers left and right using subtraction and zero, does not produce the same results, and in fact (Int,-,0) is not a monoid, because subtraction is not associative.
4. ๐ = ๐; ๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐(๐ ))

๐ = ๐; ๐ ๐  โงบ [๐ฅ] = ๐(๐ ๐  , ๐ฅ) To avoid any confusion (the definitions use the same function name ๐), and to align with the definitions on the right, letโs modify Sergeiโs definitions by doing some simple renaming. Here are Sergeiโs mathematical definitions again, on the right (the โงบ operator is list concatenation). Notice how neither definition is tail recursive. That is deliberate. As Sergei explained to me: โI'd like to avoid putting tail recursion into a mathematical formula, because tail recursion is just a detail of how we implement this functionโ and โThe fact that foldLeft is tail recursive for List is an implementation detail that is specific to the List type. It will be different for other sequence types. I do not want to put the implementation details into the formulas.โ ๐ โ ๐๐๐๐๐ ๐ โ ๐ ๐ โ ๐ ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐๐๐๐๐(๐ )) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐  โงบ [๐ฅ] = ๐(๐๐๐๐๐ ๐  , ๐ฅ) ๐ โ ๐๐๐๐๐ ๐ โ ๐ ๐ โ ๐ ๐๐๐๐๐ โท ๐ฝ โ ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ โถ ๐ฅ๐  = ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ ๐ฅ๐  ๐๐๐๐๐ โท ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ โถ ๐ฅ๐  = ๐ ๐ฅ ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  ๐ = ๐; ๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐(๐ )) ๐ = ๐; ๐ ๐  โงบ [๐ฅ] = ๐(๐ ๐  , ๐ฅ)
5. ๐๐๐๐๐ ๐ ๐ [ ] = ๐ ๐๐๐๐๐ ๐ ๐

๐ฅ โงบ ๐  = ๐ ๐ฅ (๐๐๐๐๐ ๐ ๐ ๐ ) ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐  โงบ [๐ฅ] = ๐ ๐๐๐๐๐ ๐ ๐ ๐  ๐ฅ ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐๐  = ๐ ๐๐๐๐๐ ๐ ๐ (๐๐๐๐ก ๐๐ ) (๐๐๐ ๐ก ๐๐ ) ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐๐  = ๐ โ๐๐๐ ๐๐  ๐๐๐๐๐ ๐ ๐ (๐ก๐๐๐ ๐๐ ) ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐๐  = ๐ ๐ ๐ ๐คโ๐๐๐ ๐ = ๐๐๐ ๐ก ๐๐  ๐ = ๐๐๐๐๐ ๐ ๐ (๐๐๐๐ก ๐๐ ) ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐๐  = ๐ ๐ ๐ ๐คโ๐๐๐ ๐ = โ๐๐๐ ๐๐  ๐ = ๐๐๐๐๐ ๐ ๐ (๐ก๐๐๐ ๐๐ ) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐๐๐๐๐(๐ )) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐  โงบ [๐ฅ] = ๐(๐๐๐๐๐ ๐  , ๐ฅ) To help us understand the above two definitions, letโs first express them in Haskell, pretending that we are able to use ๐  โงบ [๐ฅ] and ๐ฅ โงบ ๐  in a pattern match. Now letโs replace ๐  โงบ [๐ฅ] and ๐ฅ โงบ ๐  with as, and get the functions to extract the ๐  and the ๐ฅ using the โ๐๐๐, ๐ก๐๐๐, ๐๐๐ ๐ก and ๐๐๐๐ก. Letโs also add type signatures And now letโs make it more obvious that what each fold is doing is taking an ๐ from the list, folding the rest of the list into a ๐, and then returning the result of calling ๐ with ๐ and ๐.
6. ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐]

โ ๐ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐๐  = ๐ ๐ ๐ ๐คโ๐๐๐ ๐ = ๐๐๐ ๐ก ๐๐  ๐ = ๐๐๐๐๐ ๐ ๐ (๐๐๐๐ก ๐๐ ) ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐๐  = ๐ ๐ ๐ ๐คโ๐๐๐ ๐ = โ๐๐๐ ๐๐  ๐ = ๐๐๐๐๐ ๐ ๐ (๐ก๐๐๐ ๐๐ ) Since the above two functions are very similar, letโs extract their common logic into a fold function. Letโs call the function that is used to extract an element from the list ๐ก๐๐๐, and the function that is used to extract the rest of the list ๐๐๐ ๐ก. ๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ([๐] โ ๐) โ ([๐] โ [๐]) โ ๐ โ [๐] โ ๐ ๐๐๐๐ ๐ ๐ก๐๐๐ ๐๐๐ ๐ก ๐ = ๐ ๐๐๐๐ ๐ ๐ก๐๐๐ ๐๐๐ ๐ก ๐ ๐๐  = ๐ ๐ ๐ ๐คโ๐๐๐ ๐ = ๐ก๐๐๐ ๐๐  ๐ = ๐๐๐๐ ๐ ๐ก๐๐๐ ๐๐๐ ๐ก ๐ (๐๐๐ ๐ก ๐๐ ) We can now define left and right folds in terms of ๐๐๐๐. ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ = ๐๐๐๐ ๐ ๐๐๐ ๐ก ๐๐๐๐ก ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ = ๐๐๐๐ ๐๐๐๐ ๐ โ๐๐๐ ๐ก๐๐๐ ๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ ๐ โ ๐ ๐๐๐๐ ๐ ๐ฅ ๐ฆ = ๐ ๐ฆ ๐ฅ The slightly perplexing thing is that while a left fold applies ๐ to list elements starting with the โ๐๐๐ of the list and proceeding from left to right, the above ๐๐๐๐๐ function achieves that by navigating through list elements from right to left. Third duality theorem. For all finite lists ๐ฅ๐ , ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  = ๐๐๐๐๐ ๐๐๐๐ ๐ ๐ (๐๐๐ฃ๐๐๐ ๐ ๐ฅ๐ ) ๐๐๐๐๐ ๐๐๐๐ ๐ ๐ฅ ๐ฆ = ๐ ๐ฆ ๐ฅ The fact that we can define ๐๐๐๐๐ and ๐๐๐๐๐ in terms of ๐๐๐๐, as we do above, seems related to the third duality theorem of folding. Instead of our ๐๐๐๐๐ function being passed the reverse of the list passed to ๐๐๐๐๐, it processes the list with ๐๐๐ ๐ก and ๐๐๐๐ก, rather than with โ๐๐๐ and ๐ก๐๐๐. @philip_schwarz
7. To summarise what we did to help understand SOFPโs mathematical

definitions of left and right fold: we turned them into code and expressed them in terms of a common function ๐๐๐๐ that uses a ๐ก๐๐๐ function to extract an element from the list being folded, and a ๐๐๐ ๐ก function to extract the rest of the list. ๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ([๐] โ ๐) โ ([๐] โ [๐]) โ ๐ โ [๐] โ ๐ ๐๐๐๐ ๐ ๐ก๐๐๐ ๐๐๐ ๐ก ๐ = ๐ ๐๐๐๐ ๐ ๐ก๐๐๐ ๐๐๐ ๐ก ๐ ๐๐  = ๐ ๐ ๐ ๐คโ๐๐๐ ๐ = ๐ก๐๐๐ ๐๐  ๐ = ๐๐๐๐ ๐ ๐ก๐๐๐ ๐๐๐ ๐ก ๐ (๐๐๐ ๐ก ๐๐ ) ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ = ๐๐๐๐ ๐ ๐๐๐ ๐ก ๐๐๐๐ก ๐๐๐๐๐ :: (๐ โ ๐ โ ๐) โ ๐ โ[๐] โ ๐ ๐๐๐๐๐ ๐ = ๐๐๐๐ ๐๐๐๐ ๐ โ๐๐๐ ๐ก๐๐๐ ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐๐๐๐๐(๐ )) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐  โงบ [๐ฅ] = ๐(๐๐๐๐๐ ๐  , ๐ฅ) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐๐  = ๐(โ๐๐๐(๐๐ ), ๐๐๐๐๐(๐ก๐๐๐(๐๐ ))) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐๐  = ๐(๐๐๐๐๐ ๐๐๐๐ก(๐๐ ) , ๐๐๐ ๐ก(๐๐ )) Letโs feed one aspect of the above back into Sergeiโs definitions. Letโs temporarily rewrite them by replacing ๐  โงบ [๐ฅ] and ๐ฅ โงบ ๐  with as, and getting the definitions to extract the ๐  and the ๐ฅ using the functions โ๐๐๐, ๐ก๐๐๐, ๐๐๐ ๐ก and ๐๐๐๐ก. Notice how the flipping of ๐ done by the ๐๐๐๐๐ function above, is reflected, in the ๐๐๐๐๐ function below, in the fact that its ๐ takes an ๐ and a ๐, rather than a ๐ and an ๐.
8. Another thing we can do to understand SOFPโs definitions of

left and right folds, is to see how they work when applied to a sample list, e.g. [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ], when we run them manually. In the next slide we first do this for the following definitions ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐  โงบ [๐ฅ] = ๐(๐๐๐๐๐ ๐  , ๐ฅ) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐๐๐๐๐(๐ )) ๐๐๐๐๐ โท ๐ฝ โ ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ โถ ๐ฅ๐  = ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ ๐ฅ๐  ๐๐๐๐๐ โท ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ โถ ๐ฅ๐  = ๐ ๐ฅ ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  In the slide after that, we do it for SOFPโs definitions.
9. โถ / \ ๐ฅ0 โถ / \ ๐ฅ1 โถ /

\ ๐ฅ2 โถ / \ ๐ฅ3 ๐ / \ ๐ ๐ฅ3 / \ ๐ ๐ฅ2 / \ ๐ ๐ฅ1 / \ ๐ ๐ฅ0 ๐ / \ ๐ฅ0 ๐ / \ ๐ฅ1 ๐ / \ ๐ฅ2 ๐ / \ ๐ฅ3 ๐ ๐ฅ0 : (๐ฅ1 : ๐ฅ2 : ๐ฅ3 : ) ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 ๐ฅ3 var ๐๐๐ = ๐ foreach(๐ฅ in ๐ฅs) ๐๐๐ = ๐(๐๐๐, ๐ฅ) return ๐๐๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  ๐ฅ๐  = [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ โท ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ: ๐ฅ๐  = ๐ ๐ฅ ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  ๐๐๐๐๐ โท ๐ฝ โ ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ: ๐ฅ๐  = ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ ๐ฅ๐  ๐๐๐๐๐๐๐: โถ ๐ค๐๐กโ ๐ ๐ค๐๐กโ ๐ ๐๐๐๐๐ ๐ ๐ [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐ ๐ฅ0 ๐๐๐๐๐ ๐ ๐ [๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐ ๐ฅ0 (๐ ๐ฅ1 (๐๐๐๐๐ ๐ ๐ [๐ฅ2 , ๐ฅ3 ])) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐๐๐๐๐ ๐ ๐ [๐ฅ3 ]))) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐ ๐ฅ3 (๐๐๐๐๐ ๐ ๐ [ ])))) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐ ๐ฅ3 ๐))) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐ ๐ฅ3 ๐))) ๐๐๐๐๐ ๐ ๐ [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ0 [๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 [๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 [๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 ๐ฅ3 [ ] ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 ๐ฅ3
10. โถ / \ ๐ฅ0 โถ / \ ๐ฅ1 โถ /

\ ๐ฅ2 โถ / \ ๐ฅ3 ๐ / \ ๐ ๐ฅ3 / \ ๐ ๐ฅ2 / \ ๐ ๐ฅ1 / \ ๐ ๐ฅ0 ๐ / \ ๐ฅ0 ๐ / \ ๐ฅ1 ๐ / \ ๐ฅ2 ๐ / \ ๐ฅ3 ๐ ๐ฅ0 : (๐ฅ1 : ๐ฅ2 : ๐ฅ3 : ) ๐(๐ ๐ ๐ ๐, ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ) ๐๐๐๐๐ ๐ฅ๐  ๐๐๐๐๐ ๐ฅ๐  ๐ฅ๐  = [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐(๐ฅ3 , ๐)))) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐  โงบ [๐ฅ] = ๐(๐๐๐๐๐ ๐  , ๐ฅ) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐๐๐๐๐(๐ )) ๐๐๐๐๐ ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 , ๐ ๐๐๐๐๐ ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐(๐(๐๐๐๐๐ [๐ฅ0 , ๐ฅ1 ] , ๐ฅ2 ), ๐ฅ3 ) ๐ ๐ ๐ ๐๐๐๐๐ ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐ ๐ ๐ ๐ ๐๐๐๐๐ [ ] , ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐ ๐ ๐ ๐ ๐, ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐๐๐๐๐([๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ]) ๐(๐ฅ0 , ๐๐๐๐๐([๐ฅ1 , ๐ฅ2 , ๐ฅ3 ])) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐๐๐๐๐([๐ฅ2 , ๐ฅ3 ]))) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐๐๐๐๐([๐ฅ3 ])))) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐(๐ฅ3 , ๐๐๐๐๐([]))))) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐(๐ฅ3 , ๐))))
11. ๐๐๐๐๐ โท ๐ฝ โ ๐ผ โ ๐ฝ โ ๐ฝ โ

๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ: ๐ฅ๐  = ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ ๐ฅ๐  ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐  โงบ [๐ฅ] = ๐(๐๐๐๐๐ ๐  , ๐ฅ) โถ / \ ๐ฅ0 โถ / \ ๐ฅ1 โถ / \ ๐ฅ2 โถ / \ ๐ฅ3 ๐ฅ0 : (๐ฅ1 : ๐ฅ2 : ๐ฅ3 : ) ๐ฅ๐  = [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐ / \ ๐ ๐ฅ3 / \ ๐ ๐ฅ2 / \ ๐ ๐ฅ1 / \ ๐ ๐ฅ0 ๐๐๐๐๐ ๐ ๐ [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ฅ0 [๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 [๐ฅ2 , ๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 [๐ฅ3 ] ๐๐๐๐๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 ๐ฅ3 [ ] ๐ ๐ ๐ ๐ ๐ ๐ฅ0 ๐ฅ1 ๐ฅ2 ๐ฅ3 ๐๐๐๐๐ ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 , ๐ ๐๐๐๐๐ ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐(๐(๐๐๐๐๐ [๐ฅ0 , ๐ฅ1 ] , ๐ฅ2 ), ๐ฅ3 ) ๐ ๐ ๐ ๐๐๐๐๐ ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐ ๐ ๐ ๐ ๐๐๐๐๐ [ ] , ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ๐ ๐ ๐ ๐ ๐, ๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 Now letโs compare the results for both definitions of ๐๐๐๐๐. The results are the same. @philip_schwarz
12. ๐ / \ ๐ฅ0 ๐ / \ ๐ฅ1 ๐ /

\ ๐ฅ2 ๐ / \ ๐ฅ3 ๐ ๐๐๐๐๐ โท ๐ผ โ ๐ฝ โ ๐ฝ โ ๐ฝ โ ๐ผ โ ๐ฝ ๐๐๐๐๐ ๐ ๐ = ๐ ๐๐๐๐๐ ๐ ๐ ๐ฅ: ๐ฅ๐  = ๐ ๐ฅ ๐๐๐๐๐ ๐ ๐ ๐ฅ๐  ๐๐๐๐๐ ๐ ๐ [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐ ๐ฅ0 ๐๐๐๐๐ ๐ ๐ [๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] ๐ ๐ฅ0 (๐ ๐ฅ1 (๐๐๐๐๐ ๐ ๐ [๐ฅ2 , ๐ฅ3 ])) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐๐๐๐๐ ๐ ๐ [๐ฅ3 ]))) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐ ๐ฅ3 (๐๐๐๐๐ ๐ ๐ [ ])))) ๐ ๐ฅ0 (๐ ๐ฅ1 (๐ ๐ฅ2 (๐ ๐ฅ3 ๐))) ๐๐๐๐๐ = ๐; ๐๐๐๐๐ ๐ฅ โงบ ๐  = ๐(๐ฅ, ๐๐๐๐๐(๐ )) ๐๐๐๐๐([๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ]) ๐(๐ฅ0 , ๐๐๐๐๐([๐ฅ1 , ๐ฅ2 , ๐ฅ3 ])) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐๐๐๐๐([๐ฅ2 , ๐ฅ3 ]))) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐๐๐๐๐([๐ฅ3 ])))) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐(๐ฅ3 , ๐๐๐๐๐([]))))) ๐(๐ฅ0 , ๐(๐ฅ1 , ๐(๐ฅ2 , ๐(๐ฅ3 , ๐)))) โถ / \ ๐ฅ0 โถ / \ ๐ฅ1 โถ / \ ๐ฅ2 โถ / \ ๐ฅ3 ๐ฅ0 : (๐ฅ1 : ๐ฅ2 : ๐ฅ3 : ) ๐ฅ๐  = [๐ฅ0 , ๐ฅ1 , ๐ฅ2 , ๐ฅ3 ] And now letโs compare the results for both definitions of ๐๐๐๐๐. Again, the results are the same.
13. The way ๐๐๐๐๐ applies ๐ to ๐ฅ, ๐ฆ, z is

by associating to the right. The way ๐๐๐๐๐ does it is by associating to the right. Thinking of ๐ as an infix operator can help to grasp this. ๐๐๐๐๐ ๐(๐ฅ, ๐(๐ฆ, ๐ง)) ๐ฅ โ ๐ฆ โ ๐ง ๐๐๐๐๐ ๐ ๐ ๐ฅ, ๐ฆ , ๐ง (๐ฅ โ ๐ฆ) โ ๐ง ๐๐๐๐๐ โ ๐ ๐ฅ, ๐ฆ, z = ๐ฅ โ (๐ฆ โ ๐ง โ ๐ ) ๐๐๐๐๐ (+) 0 [1,2,3] = 1 + (2 + (3 + 0)) = 6 ๐๐๐๐๐ (+) 0 [1,2,3] = ((0 + 1) + 2) + 3 = 6 ๐๐๐๐๐ โ 0 1,2,3 = 1 โ (2 โ (3 โ 0)) = 2 ๐๐๐๐๐ โ 0 1,2,3 = ((0 โ 1) โ 2) โ 3 = โ6 โ / \ ๐ฅ โ / \ ๐ฆ โ / \ ๐ง ๐ โ / \ โ ๐ง / \ โ ๐ฆ / \ ๐ ๐ฅ ๐๐๐๐๐ โ ๐ ๐ฅ, ๐ฆ, ๐ง = ((๐ โ ๐ฅ) โ ๐ฆ) โ ๐ง Addition is associative, so associating to the left and to the right yields the same result. But subtraction isnโt associative, so associating to the left yields a result that is different to the one yielded when associating to the right.
14. We have seen that Sergeiโs definitions of left and right

folds make perfect sense. Not only are they simple and succinct, they are also free of implementation details like tail recursion. Thatโs all. I hope you found this slide deck useful. By the way, in case you are interested, see below for a whole series of slide decks dedicated to folding.