<style> .reveal .code-wrapper {width: fit-content; max-width: 200%; font-size: xxx-large;} .reveal img {max-width: 200%;} .reveal pre {max-height: 600px;} .reveal pre code {max-height: 600px; padding: 10px !important;} .reveal .hljs-ln-numbers {display: none;} code {color: #c7254e;} .fold {position: relative; left: -130px;} .tweaglogo {height: 60px; margin: 0 !important;} .haskellatwork {position: relative; left: -450px;} .list {position: relative; left: -90px; top: -70px;} .traverse {position: relative; left: -90px;} .traversePetFor {position: realtive; left: -40px;} .traverseParseEmail {position: relative; left: -60px;} .parseEmail {position: relative; left: -35px;} .foldlM {position: relative; left: -90px;} .httpCountDogs {position: relative; left: -115px;} .reveal table th, .reveal table td {border-right: 1px solid; border-color: white;} .reveal table thead tr th:last-child, .reveal table tbody tr td:last-child {border-right: none;} .reveal table tr td:first-child {font-weight: bold;} .highlight {color: #d9480f} .backgrounds {background-image: url(https://github.com/marcosh/functional-loops/blob/main/images/Tweag_Preso_BGND.svg?raw=true);} .reveal .slide-background { background-image: url(https://github.com/marcosh/functional-loops/blob/main/images/T_Mark_Orange.svg?raw=true); height: 50px; width: 50px; position: absolute; top: 20px; right: 35px; } </style> # Looping Through Functional Loops --- ## Who am I? :scroll: [marcosh.github.io](http://marcosh.github.io/) :bird: [@marcoshuttle](https://twitter.com/marcoshuttle) :elephant: [@marcosh@functional.cafe](https://functional.cafe/@marcosh) [working at ![haskell at work](https://github.com/marcosh/functional-loops/blob/main/images/Tweag_AMCC_Logo_Orange.svg?raw=true)<!-- .element: class="tweaglogo"-->](https://www.tweag.io/) --- [![haskell at work](https://github.com/marcosh/functional-loops/blob/main/images/haskellatworkheader.png?raw=true)<!-- .element: class="haskellatwork" -->](https://skillsmatter.com/workshops/883) ![qr code](https://github.com/marcosh/functional-loops/blob/main/images/Haskell%20at%20Work%20w%20Marco.png?raw=true) --- ![for loop](https://github.com/marcosh/functional-loops/blob/main/diagrams/forloop1.png?raw=true) --- ![for loop](https://github.com/marcosh/functional-loops/blob/main/diagrams/forloop2.png?raw=true) --- ![foreach](https://github.com/marcosh/functional-loops/blob/main/images/foreach.png?raw=true) --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list0.png?raw=true)<!-- .element: class="list" --> --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list1.png?raw=true)<!-- .element: class="list" --> --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list2.png?raw=true)<!-- .element: class="list" --> --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list3.png?raw=true)<!-- .element: class="list" --> --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list4.png?raw=true)<!-- .element: class="list" --> --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list5.png?raw=true)<!-- .element: class="list" --> --- ![list](https://github.com/marcosh/functional-loops/blob/main/diagrams/list6.png?raw=true)<!-- .element: class="list" --> --- ![list sugar](https://github.com/marcosh/functional-loops/blob/main/diagrams/listsugar.png?raw=true) --- ![list sugar](https://github.com/marcosh/functional-loops/blob/main/diagrams/listsugar1.png?raw=true) --- ![list sugar](https://github.com/marcosh/functional-loops/blob/main/diagrams/listsugar2.png?raw=true) --- ![list sugar](https://github.com/marcosh/functional-loops/blob/main/diagrams/listsugar3.png?raw=true) --- ```haskell 1 : (2 : (3 : (4 : (5 : []))) ``` --- ![left associativity](https://github.com/marcosh/functional-loops/blob/main/diagrams/listassociativity.png?raw=true) --- ![left associativity](https://github.com/marcosh/functional-loops/blob/main/diagrams/listsyntacticsugar.png?raw=true) --- ```haskell [1|3|5] names = ["George", "Marco", "Michael"] for (i = 0; i++; i < names.length) { lengths[i] = names[i].length } ``` --- ## map --- ![map](https://github.com/marcosh/functional-loops/blob/main/diagrams/map0.png?raw=true) --- ![map](https://github.com/marcosh/functional-loops/blob/main/diagrams/map1.png?raw=true) --- ![map](https://github.com/marcosh/functional-loops/blob/main/diagrams/map2.png?raw=true) --- ![map](https://github.com/marcosh/functional-loops/blob/main/diagrams/map3.png?raw=true) --- ```haskell map length ["George", "Marco", "Michael"] ``` --- ![map names](https://github.com/marcosh/functional-loops/blob/main/diagrams/mapnames0.png?raw=true) --- ![map names](https://github.com/marcosh/functional-loops/blob/main/diagrams/mapnames1.png?raw=true) --- ![map names](https://github.com/marcosh/functional-loops/blob/main/diagrams/mapnames2.png?raw=true) --- ![map names](https://github.com/marcosh/functional-loops/blob/main/diagrams/mapnames3.png?raw=true) --- ![map names](https://github.com/marcosh/functional-loops/blob/main/diagrams/mapnames4.png?raw=true) --- ```haskell map length ["George", "Marco", "Michael"] -- [6, 5, 7] ``` --- ## map - access one element at the time - apply a pure function to every element --- ```javascript [1|3|5|7] numbers = [1, 2, 3, 4, 5] sum = 0 for (i = 0; i++; i < numbers.length) { sum += numbers[i] } ``` --- ## fold --- ![fold](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold0.png?raw=true)<!-- .element: class="fold" --> --- ![fold](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold1.png?raw=true)<!-- .element: class="fold" --> --- ![fold](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold2.png?raw=true)<!-- .element: class="fold" --> --- ![fold](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold3.png?raw=true)<!-- .element: class="fold" --> --- ![fold](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold4.png?raw=true)<!-- .element: class="fold" --> --- ```haskell foldl (+) 0 [1, 2, 3, 4, 5] ``` --- ![foldl](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl0.png?raw=true) --- ![foldl](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl1.png?raw=true) --- ![foldl](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl2.png?raw=true) --- ![foldl](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl3.png?raw=true) --- ![foldl](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl4.png?raw=true) --- ![foldl](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl5.png?raw=true) --- ```haskell foldl (+) 0 [1, 2, 3, 4, 5] -- ((((0 + 1) + 2) + 3) + 4) + 5 ``` --- ```haskell foldl (+) 0 [1, 2, 3, 4, 5] -- ((((0 + 1) + 2) + 3) + 4) + 5 = 15 ``` --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold5.png?raw=true)<!-- .element: class="fold" --> --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl'0.png?raw=true) --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl'1.png?raw=true) --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl'2.png?raw=true) --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl'3.png?raw=true) --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl'4.png?raw=true) --- ![foldl'](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldl'5.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/fold6.png?raw=true)<!-- .element: class="fold" --> --- ```haskell foldr (+) 0 [1, 2, 3, 4, 5] ``` --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr0.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr1.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr2.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr3.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr4.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr5.png?raw=true) --- ![foldr](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldr6.png?raw=true) --- ```haskell foldr (+) 0 [1, 2, 3, 4, 5] -- 1 + (2 + (3 + (4 + (5 + 0)))) ``` --- ```haskell foldr (+) 0 [1, 2, 3, 4, 5] -- 1 + (2 + (3 + (4 + (5 + 0)))) = 15 ``` --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution0.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution1.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution2.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution3.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution4.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution5.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution6.png?raw=true) --- ![foldr substitution](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldrsubstitution7.png?raw=true) --- ## fold - accumulate elements - pure function on accumulator and item --- ```javascript [1|3|5-7|9] for (i = 0; i++; i < names.length) { pet = petFor(names[i]) if (pet == null) { return null } pets[i] = pet } ``` --- ![petFor](https://github.com/marcosh/functional-loops/blob/main/diagrams/petFor1.png?raw=true) --- ![petFor](https://github.com/marcosh/functional-loops/blob/main/diagrams/petFor2.png?raw=true) --- ```haskell [1|2] map petFor ["George", "Marco", "Michael"] -- [Just "Dharma", Nothing, Just "Curry"] ``` --- ## traverse --- ![traverse](https://github.com/marcosh/functional-loops/blob/main/diagrams/traverse0.png?raw=true)<!-- .element: class="traverse" --> --- ![traverse](https://github.com/marcosh/functional-loops/blob/main/diagrams/traverse1.png?raw=true)<!-- .element: class="traverse" --> --- ![traverse](https://github.com/marcosh/functional-loops/blob/main/diagrams/traverse2.png?raw=true)<!-- .element: class="traverse" --> --- ![traverse](https://github.com/marcosh/functional-loops/blob/main/diagrams/traverse3.png?raw=true)<!-- .element: class="traverse" --> --- ![traverse](https://github.com/marcosh/functional-loops/blob/main/diagrams/traverse4.png?raw=true)<!-- .element: class="traverse" --> --- ![traverse](https://github.com/marcosh/functional-loops/blob/main/diagrams/traverse5.png?raw=true)<!-- .element: class="traverse" --> --- ```haskell [1|2|4|5] traverse petFor ["George", "Marco", "Michael"] -- Nothing traverse petFor ["George", "Michael"] -- Just ["Dharma", "Curry"] ``` <!-- .element: class="traversePetFor" --> --- ```javascript [1|3|5-7|9] for (i = 0; i++; i < emails.length) { isValid = validateEmail(emails[i]) if (!isValid) { throw InvalidEmailException(emails[i]) } validEmails[i] = emails[i] } ``` --- ![parse email](https://github.com/marcosh/functional-loops/blob/main/diagrams/parseEmail1.png?raw=true)<!-- .element: class="parseEmail" --> --- ![parse email](https://github.com/marcosh/functional-loops/blob/main/diagrams/parseEmail2.png?raw=true)<!-- .element: class="parseEmail" --> --- ```haskell traverse :: (String -> Either Error Email) -> [String] -> Either Error [Email] ``` --- ```haskell [1|2|4|5] traverse parseEmail ["foo@bar.it", "baz@jiz.fr"] -- Right [_, _] traverse parseEmail ["foo@bar.it", "notanemail"] -- Left _ ``` <!-- .element: class="traverseParseEmail" --> --- ```javascript [1|3] for (i = 0; i++; i < names.length) { pets[i] = httpPetFor(names[i]) } ``` --- ```haskell httpPetFor :: Person -> IO Pet ``` --- ```haskell traverse :: (Person -> IO Pet) -> [Person] -> IO [Pet] ``` --- ```haskell [1|2] traverse httpPetFor ["George", "Michael"] -- ["Dharma", "Curry"] ``` --- ```haskell traverse :: Applicative f => (a -> f b) -> [a] -> f [b] --- ```haskell sequence :: Applicative f -> [f a] -> f [a] ``` --- ```haskell [1|3] traverse = sequence . map sequence = traverse id ``` --- ## traverse - access one element at the time - perform an effectful computation for every element --- ```javascript [1|3|5|7-9] countDogs = 0 for (i = 0; i++; i < names.length) { pet = httpPetFor(names[i]) if isDog(pet) { countDogs++ } } ``` --- ## fold_M --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM0.png?raw=true)<!-- .element: class="foldlM" --> --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM1.png?raw=true)<!-- .element: class="foldlM" --> --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM2.png?raw=true)<!-- .element: class="foldlM" --> --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM3.png?raw=true)<!-- .element: class="foldlM" --> --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM4.png?raw=true)<!-- .element: class="foldlM" --> --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM5.png?raw=true)<!-- .element: class="foldlM" --> --- ![foldlM](https://github.com/marcosh/functional-loops/blob/main/diagrams/foldlM6.png?raw=true)<!-- .element: class="foldlM" --> --- ```haskell [1|3-6|7] httpCountDogs :: Person -> Int -> IO Int foldlM httpCountDogs 0 ["George", "Marco", "Michael"] -- 1 ``` --- ```haskell foldlM :: Monad m => (b -> a -> m b) -> b -> [a] -> m b ``` --- ```haskell foldrM :: Monad m => (a -> b -> m b) -> b -> [a] -> m b ``` --- ## fold_M - accumulate elements - perform an effectful computation for every element --- | | pure | effectful | | ----------- | ----- | --------- | | per element | | | | aggregate | <span style="visibility: hidden;">fold_</span> | | --- | | pure<!-- .element: class="highlight" --> | effectful | | ----------- | ----- | --------- | | per element<!-- .element: class="highlight" --> | | | | aggregate | <span style="visibility: hidden;">fold_</span> | | --- | | pure<!-- .element: class="highlight" --> | effectful | | ----------- | ----- | --------- | | per element<!-- .element: class="highlight" --> | map<!-- .element: class="highlight" --> | | | aggregate | <span style="visibility: hidden;">fold_</span> | | --- | | pure<!-- .element: class="highlight" --> | effectful | | ----------- | ----- | --------- | | per element | map | | | aggregate<!-- .element: class="highlight" --> | <span style="visibility: hidden;">fold_</span> | | --- | | pure<!-- .element: class="highlight" --> | effectful | | ----------- | ----- | --------- | | per element | map | | | aggregate<!-- .element: class="highlight" --> | fold_<!-- .element: class="highlight" --> | | --- | | pure | effectful<!-- .element: class="highlight" --> | | ----------- | ----- | --------- | | per element<!-- .element: class="highlight" --> | map | | | aggregate | fold_ | | --- | | pure | effectful<!-- .element: class="highlight" --> | | ----------- | ----- | --------- | | per element<!-- .element: class="highlight" --> | map | traverse<!-- .element: class="highlight" --> | | aggregate | fold_ | | --- | | pure | effectful<!-- .element: class="highlight" --> | | ----------- | ----- | --------- | | per element | map | traverse | | aggregate<!-- .element: class="highlight" --> | fold_ | | --- | | pure | effectful<!-- .element: class="highlight" --> | | ----------- | ----- | --------- | | per element | map | traverse | | aggregate<!-- .element: class="highlight" --> | fold_ | fold_M<!-- .element: class="highlight" --> | --- # THANK YOU --- [![haskell at work](https://github.com/marcosh/functional-loops/blob/main/images/haskellatworkheader.png?raw=true)<!-- .element: class="haskellatwork" -->](https://skillsmatter.com/workshops/883) ![qr code](https://github.com/marcosh/functional-loops/blob/main/images/Haskell%20at%20Work%20w%20Marco.png?raw=true)
{"metaMigratedAt":"2023-06-17T12:51:00.502Z","metaMigratedFrom":"YAML","title":"Looping Through Functional Loops","breaks":true,"slideOptions":"{\"progress\":true,\"controls\":false,\"slideNumber\":false}","contributors":"[{\"id\":\"0893b955-bc9c-4ecc-b38c-6072b5bc1ecd\",\"add\":26382,\"del\":9318}]"}
    1392 views