(download for flawless quality)
Develop the correct intuitions of what fold left and fold right actually do, and how different these two functions are
Learn other important concepts about folding, thus reinforcing and expanding on the material seen in parts 1 and 2
Includes a brief introduction to (or refresher of) asymptotic analysis and 𝛩-notation
Part 3 - through the work of Tony Morris and Richard Bird
This document summarizes a lecture on programming methodology. The instructor begins by welcoming the students and providing some announcements, including that sections have started for Assignment 1 and the availability of help at the Tresidder computer cluster. The instructor then discusses variables in programming, explaining that a variable is a "box" that can store different values, and outlining the name, type, and value associated with each variable. The lecture covers primitive data types like int, double, boolean, and char, and provides examples of declaring and initializing variables in Java.
This document introduces exponents and explains what they are. Exponents tell us to take a number called the base and multiply it by itself a certain number of times, represented by the exponent. The base is written normally sized and the exponent is written smaller above the base. Exponents show repeated multiplication, with the exponent indicating how many times the base is multiplied. Examples are provided to illustrate exponents and their notation.
This document provides an overview of algorithms and data structures including binary search, recursion, arrays, linked lists, selection sort, and Big O notation. It explains binary search and how it is faster than simple linear search, taking logarithmic time rather than linear time. It also discusses recursion and how recursive functions require a base case to avoid infinite loops. Additionally, it compares arrays and linked lists, explaining when each is better to use, such as arrays enabling random access and linked lists facilitating efficient inserts and deletes. Selection sort is demonstrated as an O(n^2) sorting algorithm. Overall, the document serves as an introduction to fundamental algorithms and computer science concepts.
The document discusses surface structures and underlying structures in language. It provides examples of how speakers understand meanings that are not explicitly stated through surface structures alone, such as implicit knowledge of syntactic operations. The document also discusses question formations in English, including yes/no questions that use subject-auxiliary inversion and information questions that use wh-movement of question words. Underlying structures are proposed to account for this implicit syntactic knowledge, including positing an auxiliary constituent in sentence structure.
This document summarizes key points from a reading about teaching reading to students in middle and high school. It discusses how students today have different literacy demands due to technology use. It notes statistics about poor reading levels and highlights demands of common core standards. The reading advocates teaching students reading strategies to analyze and evaluate texts critically. A plan is outlined for a district-wide book study on teaching reading to older students. Teachers are reassured that incorporating some strategies weekly can help without disrupting their lessons.
Unstructure: Smashing the Boundaries of Data (SxSWi 2014)Ian Varley
When it comes to thinking about data, most software designers are stuck in a rigid, 2-dimensional mindset: "rows and columns." A shame, because breaking free from this "tyranny of the table" can bring our software to new heights: intuitive user experiences, fast development iterations, and cohesive apps.
In this workshop, we'll cover a few concepts that bring data design out of the 1970s, like: sparse representation, emergent schema, ultra-structure, prototype-driven design, graph theory, traversing the time dimension, and more. We'll run the gamut of philosophical approaches to understanding what is important in your mental (and software) model, and how to transcend your two-dimensional picture of data, and trade it in for an N-dimensional one.
Working hands-on with a simple "mock company" and its new killer app, you'll learn:
* The basic concepts of data design: entities, relationships, attributes, and types (along with a few better ways to notate them)
* How to experiment with creating these data structures in a couple existing cloud-based frameworks (e.g. google apps engine, force.com, heroku, etc.).
* How emergent techniques like schema-on-read and ultra-structure can simplify modeling (or, sometimes, complicate it)
* How statistical techniques from the data mining world can loosen our insistence on rigid models
* Why the time dimension is important (in data as well as schema)
The document discusses noun phrases and how to properly use articles (a/an, the) with nouns. It explains that a noun phrase contains a head noun and modifying words. It then covers 4 steps to determine what article to use with a noun: 1) Check if it's a proper or common noun. 2) Check if the common noun is specific or non-specific. 3) Check if a non-specific common noun is countable or uncountable. 4) Check if a countable common noun is singular or plural. Examples are provided to demonstrate applying the steps to select the correct article.
This document provides information about different types of paragraphs and how to write them effectively. It discusses descriptive, opinion, and process paragraphs. For each type, it outlines the key components and offers guidelines. Descriptive paragraphs explain how something looks, feels, etc. Opinion paragraphs state the writer's opinion on a topic and back it up with facts. Process paragraphs explain how to do something by breaking it into a series of steps. The document also covers other topics like using adjectives, facts vs opinions, and transition words to connect ideas between sentences and paragraphs.
This document summarizes a lecture on programming methodology. The instructor begins by welcoming the students and providing some announcements, including that sections have started for Assignment 1 and the availability of help at the Tresidder computer cluster. The instructor then discusses variables in programming, explaining that a variable is a "box" that can store different values, and outlining the name, type, and value associated with each variable. The lecture covers primitive data types like int, double, boolean, and char, and provides examples of declaring and initializing variables in Java.
This document introduces exponents and explains what they are. Exponents tell us to take a number called the base and multiply it by itself a certain number of times, represented by the exponent. The base is written normally sized and the exponent is written smaller above the base. Exponents show repeated multiplication, with the exponent indicating how many times the base is multiplied. Examples are provided to illustrate exponents and their notation.
This document provides an overview of algorithms and data structures including binary search, recursion, arrays, linked lists, selection sort, and Big O notation. It explains binary search and how it is faster than simple linear search, taking logarithmic time rather than linear time. It also discusses recursion and how recursive functions require a base case to avoid infinite loops. Additionally, it compares arrays and linked lists, explaining when each is better to use, such as arrays enabling random access and linked lists facilitating efficient inserts and deletes. Selection sort is demonstrated as an O(n^2) sorting algorithm. Overall, the document serves as an introduction to fundamental algorithms and computer science concepts.
The document discusses surface structures and underlying structures in language. It provides examples of how speakers understand meanings that are not explicitly stated through surface structures alone, such as implicit knowledge of syntactic operations. The document also discusses question formations in English, including yes/no questions that use subject-auxiliary inversion and information questions that use wh-movement of question words. Underlying structures are proposed to account for this implicit syntactic knowledge, including positing an auxiliary constituent in sentence structure.
This document summarizes key points from a reading about teaching reading to students in middle and high school. It discusses how students today have different literacy demands due to technology use. It notes statistics about poor reading levels and highlights demands of common core standards. The reading advocates teaching students reading strategies to analyze and evaluate texts critically. A plan is outlined for a district-wide book study on teaching reading to older students. Teachers are reassured that incorporating some strategies weekly can help without disrupting their lessons.
Unstructure: Smashing the Boundaries of Data (SxSWi 2014)Ian Varley
When it comes to thinking about data, most software designers are stuck in a rigid, 2-dimensional mindset: "rows and columns." A shame, because breaking free from this "tyranny of the table" can bring our software to new heights: intuitive user experiences, fast development iterations, and cohesive apps.
In this workshop, we'll cover a few concepts that bring data design out of the 1970s, like: sparse representation, emergent schema, ultra-structure, prototype-driven design, graph theory, traversing the time dimension, and more. We'll run the gamut of philosophical approaches to understanding what is important in your mental (and software) model, and how to transcend your two-dimensional picture of data, and trade it in for an N-dimensional one.
Working hands-on with a simple "mock company" and its new killer app, you'll learn:
* The basic concepts of data design: entities, relationships, attributes, and types (along with a few better ways to notate them)
* How to experiment with creating these data structures in a couple existing cloud-based frameworks (e.g. google apps engine, force.com, heroku, etc.).
* How emergent techniques like schema-on-read and ultra-structure can simplify modeling (or, sometimes, complicate it)
* How statistical techniques from the data mining world can loosen our insistence on rigid models
* Why the time dimension is important (in data as well as schema)
The document discusses noun phrases and how to properly use articles (a/an, the) with nouns. It explains that a noun phrase contains a head noun and modifying words. It then covers 4 steps to determine what article to use with a noun: 1) Check if it's a proper or common noun. 2) Check if the common noun is specific or non-specific. 3) Check if a non-specific common noun is countable or uncountable. 4) Check if a countable common noun is singular or plural. Examples are provided to demonstrate applying the steps to select the correct article.
This document provides information about different types of paragraphs and how to write them effectively. It discusses descriptive, opinion, and process paragraphs. For each type, it outlines the key components and offers guidelines. Descriptive paragraphs explain how something looks, feels, etc. Opinion paragraphs state the writer's opinion on a topic and back it up with facts. Process paragraphs explain how to do something by breaking it into a series of steps. The document also covers other topics like using adjectives, facts vs opinions, and transition words to connect ideas between sentences and paragraphs.
This document provides a guide for students to learn and practice phrasal verbs. It begins with an introduction explaining what phrasal verbs are and why they are important to learn in English. The guide then covers basic rules for phrasal verbs, different types including prepositional and three-word verbs, and provides examples and exercises for students to practice. It aims to help English language learners improve their understanding and use of these common multi-word verbs.
1. The document discusses Thomas Schelling's model of how people choose seats at a conference based on their behavior and choices in relation to others.
2. It introduces Schelling's observation of empty front rows and full back rows at a conference, and his use of Lave and March's 4 step model to speculate about the processes that could produce this pattern.
3. Key points discussed include linking micro-level individual behavior to macro-level aggregate outcomes, and how people's choices depend on and respond to the choices of others around them in complex ways that are not simple extrapolations.
Common Writing Mistakes On College Essays JoyceMeghan Howard
The World Wide Web (WWW or W3) emerged as the most popular and successful hypertext system despite other sophisticated competitors. It achieved this through its open and universal accessibility from any device with a browser. The WWW used simple but effective technologies like HTTP, HTML, and URLs that allowed for easy creation and sharing of hyperlinked documents across diverse platforms and operating systems. Though other systems offered richer navigation features, the WWW's openness and simplicity made it the system that linked the greatest number of hypertext documents worldwide.
This document outlines the agenda for a class on rhetoric, including an icebreaker, overview of the course's first assignment, and freewriting exercises. It introduces Aristotle's rhetorical triangle of ethos, pathos, and logos. Ethos refers to appeals based on authority or expertise, pathos to emotion, and logos to logic. It also maps these concepts onto characters from Star Trek to help with memorization. The document provides prompts to guide students through a freewriting exercise connected to technologies and writing habits. It concludes with assigning homework on an online forum.
This document provides guidance and strategies for teaching vocabulary. It begins with guiding questions about what vocabulary is, why it should be taught, and how to choose words. It then discusses effective vocabulary teaching strategies such as using a print-rich environment, explicit instruction of word meanings, and promoting independent word learning. Specific activities that support vocabulary learning are also mentioned, such as word splashes, word tiers, cognates, morphology, games, projects and extensive reading. Resources on graphic organizers, prefixes/suffixes, Latin/Greek roots are also provided.
The document discusses different roles and responsibilities people have. It provides examples of responsibilities of police officers, leaders, teachers, pilots, dog owners, and responsibilities for different rooms in a house. Students are prompted to think about roles they have and responsibilities within each role. An activity is described where students write responsibilities on cards for different rooms and try to match the responsibility to the correct room.
The text discusses two major approaches to analyzing the structure of conversations: the Birmingham/Structural Approach and Conversation Analysis (CA). The Birmingham/Structural Approach focuses on the sequential organization of interaction, particularly in institutional settings, and sees interaction as being governed by a syntax of action. CA, on the other hand, is concerned with the contextual sensitivity of language use and talk as a means of social action, and was developed as a reaction to deterministic models of society. Both approaches aim to better understand the structure of conversations and how they contribute to mutual understanding.
This document provides information about conjunctions. It begins by asking the reader to recall what conjunctions are and has students write their answers on whiteboards. It then lists the learning objectives as being able to identify and recognize conjunctions, and to use conjunctions to improve sentences. The document provides examples of common conjunctions like "and", "but", and "or" and how they can be used to join sentences or show differences. It highlights exercises for students to identify conjunctions in sentences and uses conjunctions to join sentences. The document emphasizes using a variety of conjunctions to improve writing and provides tips and a rhyme to help remember conjunctions. It discusses assessment criteria and has students complete tasks to develop portfolios for famous
1. Think “Relevant ==> Simple ==> Intricate.”
2. Visualize “mastery blocks.”
3. Generate comprehensive examples.
4. Assessment.
5. End with lead to next topic.
Here are revised versions of the sentences using "only" in a more precise location:
1. The clerk reviewed the statement for the purpose of checking only for errors.
2. All the students must know only the absolutely basic fundamentals of grammar.
3. The politician tried to only make his influence felt among the citizens.
4. The bank teller asked the customer to only endorse the check on the back.
5. The governor’s assistant gave only a speech on the subject of the resources of Texas.
6. The patient was to only take his medicine at regular intervals of time.
Step-By-Step Guide to Essay Writing - ESL Buzz. Academic Essay Writing, Best Essay Writing Service, Essay Writer .... Helpful pieces of advice on how to write an effective essay | Academic .... Essay Writing Examples - 21+ Samples in PDF | DOC | Examples. Essay, Essay writing, Essay writing help, Essay writing tips. Help in essay writing - College Homework Help and Online Tutoring.. FREE 9+ College Essay Examples in PDF | Examples - How to write english .... School essay: Argumentative essay sample for college. College Essay Format: Simple Steps to Be Followed. 10 Tips to Write an Essay and Actually Enjoy It. Help writing an essay. How To Write an Essay - The steps to writing an essay This Instructable .... Best Essay Writing Service Online - USA, UK, Australia. Simple Guide to Help You Write an Essay by BreeAndrea - Issuu. Essay About Help - Scholarship essay help tips. Why Essay Writing Help Is Important For Students These Days? | Custom .... Top Considerations in Choosing the Best Essay Writing Service. How to Write a Great Essay Quickly! – ESL Buzz. Help with essay writing - College Homework Help and Online Tutoring.. College Essay: Help with essays. 24 Greatest College Essay Examples – RedlineSP. Essay Writing Tips That Will Make College a Breeze - LVDletters.
Hand Rolled Applicative User ValidationCode KataPhilip Schwarz
Could you use a simple piece of Scala validation code (granted, a very simplistic one too!) that you can rewrite, now and again, to refresh your basic understanding of Applicative operators <*>, <*, *>?
The goal is not to write perfect code showcasing validation, but rather, to provide a small, rough-and ready exercise to reinforce your muscle-memory.
Despite its grandiose-sounding title, this deck consists of just three slides showing the Scala 3 code to be rewritten whenever the details of the operators begin to fade away.
The code is my rough and ready translation of a Haskell user-validation program found in a book called Finding Success (and Failure) in Haskell - Fall in love with applicative functors.
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidPhilip Schwarz
The subject of this deck is the small Print[A] program in the following blog post by Noel Welsh: https://www.inner-product.com/posts/direct-style-effects/.
Keywords: "direct-style", "context function", "context functions", "algebraic effect", "algebraic effects", "scala", "effect system", "effect systems", "effect", "side effect", "composition", "fp", "functional programming"
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
For functions that can be defined both as an instance of a right fold and as an instance of a left fold, one may be more efficient than the other.
Let's look at the example of a function 'decimal' that converts a list of digits into the corresponding decimal number.
Erratum: it has been pointed out that it is possible to define the zip function using a right fold (see slide 5).
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
This document summarizes the universal property of fold, which states that for finite lists the fold function is the unique function that satisfies its defining recursive equations. It provides examples of how common list functions like sum, product, length, concatenation (⧺) can be defined in terms of fold. It also notes that the universal property can be generalized to handle partial and infinite lists. Finally, it states that map, filter and fold form the "triad" or basic building blocks of functional programming.
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
This document provides definitions and examples of foldr and foldl functions in functional programming. Foldr recursively applies a function from right to left, associating at each step. Foldl recursively applies a function from left to right, associating at each step. Examples are given applying foldr and foldl to a list with elements a0 through a3, using a function f and initial value b. Programmatic and mathematical definitions of foldr and foldl are also presented.
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
This document provides examples of using fold functions to define recursive functions over natural numbers (Nat) and lists. It shows common patterns for defining recursive functions over Nat using foldn and over lists using foldr. Three examples are given of functions defined over Nat using foldn: addition, multiplication, and exponentiation. Three examples are also given of functions defined over lists using foldr: sum, length, and append.
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
Tagless Final Encoding - Algebras and Interpreters and also Programs - An introduction, through the work of Gabriel Volpe.
Slide deck home: http://fpilluminated.com/assets/tagless-final-encoding-algebras-interpreters-and-programs.html
This document provides a guide for students to learn and practice phrasal verbs. It begins with an introduction explaining what phrasal verbs are and why they are important to learn in English. The guide then covers basic rules for phrasal verbs, different types including prepositional and three-word verbs, and provides examples and exercises for students to practice. It aims to help English language learners improve their understanding and use of these common multi-word verbs.
1. The document discusses Thomas Schelling's model of how people choose seats at a conference based on their behavior and choices in relation to others.
2. It introduces Schelling's observation of empty front rows and full back rows at a conference, and his use of Lave and March's 4 step model to speculate about the processes that could produce this pattern.
3. Key points discussed include linking micro-level individual behavior to macro-level aggregate outcomes, and how people's choices depend on and respond to the choices of others around them in complex ways that are not simple extrapolations.
Common Writing Mistakes On College Essays JoyceMeghan Howard
The World Wide Web (WWW or W3) emerged as the most popular and successful hypertext system despite other sophisticated competitors. It achieved this through its open and universal accessibility from any device with a browser. The WWW used simple but effective technologies like HTTP, HTML, and URLs that allowed for easy creation and sharing of hyperlinked documents across diverse platforms and operating systems. Though other systems offered richer navigation features, the WWW's openness and simplicity made it the system that linked the greatest number of hypertext documents worldwide.
This document outlines the agenda for a class on rhetoric, including an icebreaker, overview of the course's first assignment, and freewriting exercises. It introduces Aristotle's rhetorical triangle of ethos, pathos, and logos. Ethos refers to appeals based on authority or expertise, pathos to emotion, and logos to logic. It also maps these concepts onto characters from Star Trek to help with memorization. The document provides prompts to guide students through a freewriting exercise connected to technologies and writing habits. It concludes with assigning homework on an online forum.
This document provides guidance and strategies for teaching vocabulary. It begins with guiding questions about what vocabulary is, why it should be taught, and how to choose words. It then discusses effective vocabulary teaching strategies such as using a print-rich environment, explicit instruction of word meanings, and promoting independent word learning. Specific activities that support vocabulary learning are also mentioned, such as word splashes, word tiers, cognates, morphology, games, projects and extensive reading. Resources on graphic organizers, prefixes/suffixes, Latin/Greek roots are also provided.
The document discusses different roles and responsibilities people have. It provides examples of responsibilities of police officers, leaders, teachers, pilots, dog owners, and responsibilities for different rooms in a house. Students are prompted to think about roles they have and responsibilities within each role. An activity is described where students write responsibilities on cards for different rooms and try to match the responsibility to the correct room.
The text discusses two major approaches to analyzing the structure of conversations: the Birmingham/Structural Approach and Conversation Analysis (CA). The Birmingham/Structural Approach focuses on the sequential organization of interaction, particularly in institutional settings, and sees interaction as being governed by a syntax of action. CA, on the other hand, is concerned with the contextual sensitivity of language use and talk as a means of social action, and was developed as a reaction to deterministic models of society. Both approaches aim to better understand the structure of conversations and how they contribute to mutual understanding.
This document provides information about conjunctions. It begins by asking the reader to recall what conjunctions are and has students write their answers on whiteboards. It then lists the learning objectives as being able to identify and recognize conjunctions, and to use conjunctions to improve sentences. The document provides examples of common conjunctions like "and", "but", and "or" and how they can be used to join sentences or show differences. It highlights exercises for students to identify conjunctions in sentences and uses conjunctions to join sentences. The document emphasizes using a variety of conjunctions to improve writing and provides tips and a rhyme to help remember conjunctions. It discusses assessment criteria and has students complete tasks to develop portfolios for famous
1. Think “Relevant ==> Simple ==> Intricate.”
2. Visualize “mastery blocks.”
3. Generate comprehensive examples.
4. Assessment.
5. End with lead to next topic.
Here are revised versions of the sentences using "only" in a more precise location:
1. The clerk reviewed the statement for the purpose of checking only for errors.
2. All the students must know only the absolutely basic fundamentals of grammar.
3. The politician tried to only make his influence felt among the citizens.
4. The bank teller asked the customer to only endorse the check on the back.
5. The governor’s assistant gave only a speech on the subject of the resources of Texas.
6. The patient was to only take his medicine at regular intervals of time.
Step-By-Step Guide to Essay Writing - ESL Buzz. Academic Essay Writing, Best Essay Writing Service, Essay Writer .... Helpful pieces of advice on how to write an effective essay | Academic .... Essay Writing Examples - 21+ Samples in PDF | DOC | Examples. Essay, Essay writing, Essay writing help, Essay writing tips. Help in essay writing - College Homework Help and Online Tutoring.. FREE 9+ College Essay Examples in PDF | Examples - How to write english .... School essay: Argumentative essay sample for college. College Essay Format: Simple Steps to Be Followed. 10 Tips to Write an Essay and Actually Enjoy It. Help writing an essay. How To Write an Essay - The steps to writing an essay This Instructable .... Best Essay Writing Service Online - USA, UK, Australia. Simple Guide to Help You Write an Essay by BreeAndrea - Issuu. Essay About Help - Scholarship essay help tips. Why Essay Writing Help Is Important For Students These Days? | Custom .... Top Considerations in Choosing the Best Essay Writing Service. How to Write a Great Essay Quickly! – ESL Buzz. Help with essay writing - College Homework Help and Online Tutoring.. College Essay: Help with essays. 24 Greatest College Essay Examples – RedlineSP. Essay Writing Tips That Will Make College a Breeze - LVDletters.
Similaire à Folding Unfolded -Polyglot FP for Fun and Profit -Haskell and Scala - Part 3 (12)
Hand Rolled Applicative User ValidationCode KataPhilip Schwarz
Could you use a simple piece of Scala validation code (granted, a very simplistic one too!) that you can rewrite, now and again, to refresh your basic understanding of Applicative operators <*>, <*, *>?
The goal is not to write perfect code showcasing validation, but rather, to provide a small, rough-and ready exercise to reinforce your muscle-memory.
Despite its grandiose-sounding title, this deck consists of just three slides showing the Scala 3 code to be rewritten whenever the details of the operators begin to fade away.
The code is my rough and ready translation of a Haskell user-validation program found in a book called Finding Success (and Failure) in Haskell - Fall in love with applicative functors.
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidPhilip Schwarz
The subject of this deck is the small Print[A] program in the following blog post by Noel Welsh: https://www.inner-product.com/posts/direct-style-effects/.
Keywords: "direct-style", "context function", "context functions", "algebraic effect", "algebraic effects", "scala", "effect system", "effect systems", "effect", "side effect", "composition", "fp", "functional programming"
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
For functions that can be defined both as an instance of a right fold and as an instance of a left fold, one may be more efficient than the other.
Let's look at the example of a function 'decimal' that converts a list of digits into the corresponding decimal number.
Erratum: it has been pointed out that it is possible to define the zip function using a right fold (see slide 5).
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
This document summarizes the universal property of fold, which states that for finite lists the fold function is the unique function that satisfies its defining recursive equations. It provides examples of how common list functions like sum, product, length, concatenation (⧺) can be defined in terms of fold. It also notes that the universal property can be generalized to handle partial and infinite lists. Finally, it states that map, filter and fold form the "triad" or basic building blocks of functional programming.
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
This document provides definitions and examples of foldr and foldl functions in functional programming. Foldr recursively applies a function from right to left, associating at each step. Foldl recursively applies a function from left to right, associating at each step. Examples are given applying foldr and foldl to a list with elements a0 through a3, using a function f and initial value b. Programmatic and mathematical definitions of foldr and foldl are also presented.
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
This document provides examples of using fold functions to define recursive functions over natural numbers (Nat) and lists. It shows common patterns for defining recursive functions over Nat using foldn and over lists using foldr. Three examples are given of functions defined over Nat using foldn: addition, multiplication, and exponentiation. Three examples are also given of functions defined over lists using foldr: sum, length, and append.
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
Tagless Final Encoding - Algebras and Interpreters and also Programs - An introduction, through the work of Gabriel Volpe.
Slide deck home: http://fpilluminated.com/assets/tagless-final-encoding-algebras-interpreters-and-programs.html
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
Slide deck home: http://fpilluminated.com/assets/sighting-of-scala-cats-traverseFilter-and-foldMap-in-practical-fp-in-scala.html.
Download PDF for perfect image quality.
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
Slide deck home: http://fpilluminated.com/assets/sighting-of-scala-cats-sequence-function-in-practical-fp-in-scala.html.
Download PDF for perfect image quality.
This talk was presented on Aug 3rd 2023 during the Scala in the City event a ITV in London https://www.meetup.com/scala-in-the-city/events/292844968/
Visit the following for a description, slideshow, all slides with transcript, pdf, github repo, and eventually a video recording: http://fpilluminated.com/assets/n-queens-combinatorial-puzzle-meets-cats.html
At the centre of this talk is the N-Queens combinatorial puzzle. The reason why this puzzle features in the Scala book and functional programming course by Martin Odersky (the language’s creator), is that such puzzles are a particularly suitable application area of 'for comprehensions'.
We’ll start by (re)acquainting ourselves with the puzzle, and seeing the role played in it by permutations. Next, we’ll see how, when wanting to visualise candidate puzzle solutions, Cats’ monoidal functions fold and foldMap are a great fit for combining images.
While we are all very familiar with the triad providing the bread, butter and jam of functional programming, i.e. map, filter and fold, not everyone knows about the corresponding functions in Cats’ monadic variant of the triad, i.e. mapM, filterM and foldM, which we are going to learn about next.
As is often the case in functional programming, the traverse function makes an appearance, and we shall grab the opportunity to point out the symmetry that exists in the interrelation of flatMap / foldMap / traverse and flatten / fold / sequence.
Armed with an understanding of foldM, we then look at how such a function can be used to implement an iterative algorithm for the N-Queens puzzle.
The talk ends by pointing out that the iterative algorithm is smarter than the recursive one, because it ‘remembers’ where it has already placed previous queens.
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
Kleisli composition, flatMap, join, map, unit. A study/memory aid, to help learn/recall their implementation/interrelation.
Version 2, updated for Scala 3
Nat, List and Option Monoids -from scratch -Combining and Folding -an examplePhilip Schwarz
Nat, List and Option Monoids, from scratch. Combining and Folding: an example.
This is a new version of the original which has some cosmetic changes and a new 7th slide which only differs from slide 6 in that it defines the fold function in terms of the foldRight function.
Code: https://github.com/philipschwarz/nat-list-and-option-monoids-from-scratch-combining-and-folding-an-example
Nat, List and Option Monoids -from scratch -Combining and Folding -an examplePhilip Schwarz
Nat, List and Option Monoids, from scratch. Combining and Folding: an example.
Code: https://github.com/philipschwarz/nat-list-and-option-monoids-from-scratch-combining-and-folding-an-example
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
When I posted the deck for Part 1 to the Scala users forum, Odd Möller linked to a paper titled "The Genuine Sieve of Eratosthenes", which speaks of the Unfaithful Sieve.
Part 2 is based on that paper and on Richard Bird's faithful Haskell implementation of the Sieve, which we translate into Scala.
Scala code for Richard Bird's infinite primes Haskell program: https://github.com/philipschwarz/sieve-of-eratosthenes-part-2-scala
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
- The document describes how product types (built using AND) and sum types (built using OR) are used to define types for representing fruit salads and fruit snacks in F#, Haskell, Scala, and Java.
- Product types combine elements and are used to define the FruitSalad type, while sum types allow alternatives and are used to define the FruitSnack type consisting of different fruits.
- Pattern matching is demonstrated to write functions that analyze and return different strings based on the values of FruitSalad and FruitSnack types.
Using Query Store in Azure PostgreSQL to Understand Query PerformanceGrant Fritchey
Microsoft has added an excellent new extension in PostgreSQL on their Azure Platform. This session, presented at Posette 2024, covers what Query Store is and the types of information you can get out of it.
Unveiling the Advantages of Agile Software Development.pdfbrainerhub1
Learn about Agile Software Development's advantages. Simplify your workflow to spur quicker innovation. Jump right in! We have also discussed the advantages.
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsPeter Muessig
The UI5 tooling is the development and build tooling of UI5. It is built in a modular and extensible way so that it can be easily extended by your needs. This session will showcase various tooling extensions which can boost your development experience by far so that you can really work offline, transpile your code in your project to use even newer versions of EcmaScript (than 2022 which is supported right now by the UI5 tooling), consume any npm package of your choice in your project, using different kind of proxies, and even stitching UI5 projects during development together to mimic your target environment.
What to do when you have a perfect model for your software but you are constrained by an imperfect business model?
This talk explores the challenges of bringing modelling rigour to the business and strategy levels, and talking to your non-technical counterparts in the process.
Mobile App Development Company In Noida | Drona InfotechDrona Infotech
Drona Infotech is a premier mobile app development company in Noida, providing cutting-edge solutions for businesses.
Visit Us For : https://www.dronainfotech.com/mobile-application-development/
WWDC 2024 Keynote Review: For CocoaCoders AustinPatrick Weigel
Overview of WWDC 2024 Keynote Address.
Covers: Apple Intelligence, iOS18, macOS Sequoia, iPadOS, watchOS, visionOS, and Apple TV+.
Understandable dialogue on Apple TV+
On-device app controlling AI.
Access to ChatGPT with a guest appearance by Chief Data Thief Sam Altman!
App Locking! iPhone Mirroring! And a Calculator!!
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfVALiNTRY360
Salesforce Healthcare CRM, implemented by VALiNTRY360, revolutionizes patient management by enhancing patient engagement, streamlining administrative processes, and improving care coordination. Its advanced analytics, robust security, and seamless integration with telehealth services ensure that healthcare providers can deliver personalized, efficient, and secure patient care. By automating routine tasks and providing actionable insights, Salesforce Healthcare CRM enables healthcare providers to focus on delivering high-quality care, leading to better patient outcomes and higher satisfaction. VALiNTRY360's expertise ensures a tailored solution that meets the unique needs of any healthcare practice, from small clinics to large hospital systems.
For more info visit us https://valintry360.com/solutions/health-life-sciences
Transform Your Communication with Cloud-Based IVR SolutionsTheSMSPoint
Discover the power of Cloud-Based IVR Solutions to streamline communication processes. Embrace scalability and cost-efficiency while enhancing customer experiences with features like automated call routing and voice recognition. Accessible from anywhere, these solutions integrate seamlessly with existing systems, providing real-time analytics for continuous improvement. Revolutionize your communication strategy today with Cloud-Based IVR Solutions. Learn more at: https://thesmspoint.com/channel/cloud-telephony
E-commerce Development Services- Hornet DynamicsHornet Dynamics
For any business hoping to succeed in the digital age, having a strong online presence is crucial. We offer Ecommerce Development Services that are customized according to your business requirements and client preferences, enabling you to create a dynamic, safe, and user-friendly online store.
Folding Unfolded -Polyglot FP for Fun and Profit -Haskell and Scala - Part 3
1. Develop the correct intuitions of what fold left and fold right actually do, and how different these two functions are
Learn other important concepts about folding, thus reinforcing and expanding on the material seen in parts 1 and 2
Includes a brief introduction to (or refresher of) asymptotic analysis and 𝛩-notation
Part 3 - through the work of
Folding Unfolded
Polyglot FP for Fun and Profit
Haskell and Scala
@philip_schwarzslides by https://www.slideshare.net/pjschwarz
Richard Bird
http://www.cs.ox.ac.uk/people/richard.bird/
Tony Morris
@dibblego
https://presentations.tmorris.net/
2. In this part of the series we are going to go through what I think is a very useful talk by Tony Morris.
While it is a beginner level talk, IMHO Tony does a great job of explaining a number of important concepts about folding, including the
correct intuitions to have about what fold left and fold right actually do, and how different these two functions are are.
And as usual, we’ll be looking for opportunities to expand on some topics and making a number of other interesting observations, allowing
us to reinforce and expand on what we have already learnt in Parts 1 and 2.
Tony Morris
@dibblego
https://presentations.tmorris.net/
3. Hello, my name is Tony Morris.
I am going to talk to you today about list folds.
It’s a beginner level talk. I am hoping to transfer some knowledge to you to think abut list folds so that you can really
understand how they work. …
OK so what are the goals for today?
Who has heard of left and right fold on lists? And for those of you who have your hand up, is that the end of your
knowledge? That’s it, you just heard of them? You have heard of them but that’s it. A few people.
My goal today is to transfer you some knowledge so that you can understand internally what they do.
I get a lot of questions about them in my email. Can you tell me when to use the right one? What does this one do? What
does that one do? How do I think about them?
I want to answer these questions.
I have heard of these folds… left and right
• What do they do?
• How do I know when to use them?
• Which one do I use?
• Can I internalize how they work?Tony Morris
@dibblego
4. First we have to talk about what exactly is a list.
What is a list?
A list is either 𝑵𝒊𝒍, an empty list, it carries no information, it is just an empty list.
Or, it has one element, and then another list.
Think about lists this way. I can make any list this way.
Using either 𝑵𝒊𝒍 or 𝑪𝒐𝒏𝒔. 𝑵𝒊𝒍 being an empty list. 𝑪𝒐𝒏𝒔 having one element and then another list.
It is never anything else. It is always 𝑵𝒊𝒍 or 𝑪𝒐𝒏𝒔.
a list is either
• a 𝑵𝒊𝒍 construction, with no associated data
• A 𝑪𝒐𝒏𝒔 construction, associated with one arbitrary value, and another list
And never, ever anything else
Tony Morris
@dibblego
5. So this is the Haskell signature for them:
So we say that 𝑵𝒊𝒍 is just a 𝑳𝒊𝒔𝒕 of elements 𝑎, it’s the empty list.
And 𝑪𝒐𝒏𝒔 takes an 𝑎, the first element, and then a 𝑳𝒊𝒔𝒕 𝑎, the rest of the list, and it makes a new list.
The word 𝑪𝒐𝒏𝒔 by the way goes back to the 1950s. We tend not to make up new words when they are that well
established.
Here is the Haskell source code:
What this says is we are declaring a data type called 𝑳𝒊𝒔𝒕, carrying elements of type 𝑎. It is made with 𝑵𝒊𝒍, that has nothing,
or with 𝑪𝒐𝒏𝒔, that has an 𝑎 and another 𝑳𝒊𝒔𝒕 of 𝑎.
A list that holds elements of type a is constructed by either:
𝑵𝒊𝒍 ∷ 𝑳𝒊𝒔𝒕 𝑎
𝑪𝒐𝒏𝒔 ∷ 𝑎 → 𝑳𝒊𝒔𝒕 𝑎 → 𝑳𝒊𝒔𝒕 𝑎
A list declaration using Haskell
𝐝𝐚𝐭𝐚 𝑳𝒊𝒔𝒕 𝑎 = 𝑵𝒊𝒍 | 𝑪𝒐𝒏𝒔 𝑎 (𝑳𝒊𝒔𝒕 𝑎)
Tony Morris
@dibblego
6. How can we make lists using this?
For example, here is a list that has one element, the number 12. I have called 𝑪𝒐𝒏𝒔, I passed in one element, 12, and then
the rest of the list, 𝑵𝒊𝒍, there is no rest of the list.
What about the list abc? I call 𝑪𝒐𝒏𝒔, I pass in the letter ‘a’, then I have to pass in another list, so then I call 𝑪𝒐𝒏𝒔, and the
letter ‘b’, need to pass in another list, 𝑪𝒐𝒏𝒔, ‘c’, 𝑵𝒊𝒍.
I can make any list using 𝑪𝒐𝒏𝒔 and 𝑵𝒊𝒍. That’s the definition of a list, or a 𝑪𝒐𝒏𝒔 list as they are sometimes known.
Haskell
𝑪𝒐𝒏𝒔 12 𝑵𝒊𝒍
printed
[12]
Haskell
𝑪𝒐𝒏𝒔 ‘a’ (𝑪𝒐𝒏𝒔 ‘b’ (𝑪𝒐𝒏𝒔 ‘c’ 𝑵𝒊𝒍))
printed
[‘a’, ’b’, ’c’]
Tony Morris
@dibblego
7. Sometimes you’ll see 𝑵𝒊𝒍 spelt square brackets. It’s the same thing.
Sometimes you’ll see 𝑪𝒐𝒏𝒔 as just a colon, or sometimes a double colon, depending on the language.
So here is the list 1-2-3: one, 𝑪𝒐𝒏𝒔, and then a whole new list, 2, 𝑪𝒐𝒏𝒔, and then a whole new list, 3, 𝑪𝒐𝒏𝒔 and then 𝑵𝒊𝒍.
This is the definition of a list. This is how we make them.
So when we talk about fold, we talk about these kinds of lists.
Footnote: there are languages for which this is not true. They talk about other kinds of lists. But if we consider C# for
example, it has an aggregate function which is a kind of fold, but it works on other kinds of lists, so it is not really a fold.
So I am just going to talk about it in terms of 𝑪𝒐𝒏𝒔 lists.
Naming conventions
• sometimes you will see 𝑵𝒊𝒍 denoted []
• and 𝑪𝒐𝒏𝒔 denoted : which is used in infix position
• like this 1 :(2 :(3 :[]))
• but this is the same data structure
Tony Morris
@dibblego
8. Nearly two thirds of you have put your hand up, you have heard about left fold and right fold. Heard of them, that’s it.
Walking down the street one day, someone said “left and right fold”, and then you just kept walking.
In Haskell they are called foldr and foldl. In Scala they are called foldRight, and foldLeft. And C# has this function
called Aggregate, which is essentially a foldLeft (kind of).
Just to be clear on our goals, when do I know to use a fold? What problem do I have so that I am going to use a fold? Which
one am I going to use? And finally, what do they do? What is a good way to think about what they do?
Left, Right, FileNotFound
• you may have heard of right folds and left folds
• Haskell: foldr, foldl
• Scala: foldRight, foldLeft
• C# (BCL): no right fold, Aggregate (kind of)
Developing intuition for folds
• When do I know to use a fold?
• When do I know which fold to use?
• What do the fold functions actually do?
Tony Morris
@dibblego
9. You might have seen these diagrams, they are on the internet. They are pretty good diagrams. They
are quite accurate. They don’t really help I think, in my experience.
People come up to me and say: can you tell me exactly what a right fold is? And I show them this
diagram. And they go: I still don’t know what a right fold does. It needs some explanation.
There is much effort toward answering these questions
Figure: right fold diagram
Tony Morris
@dibblego
10. This is a left fold diagram: it didn’t help.
And sometimes you probably heard of this
The right fold does folding from the right and left fold from the left. Not only it is not helpful, it is not even true.
I have also heard this: we are going to use the right fold when we need to work with an infinite list. This is not correct, OK?
Sometimes they are just not right.
There is much effort toward answering these questions
Figure: left fold diagram
and terse explanations
• the right fold does folding from the right and left fold, folding from the left
• choose the right fold when you need to work with an infinite list
Unfortunately
some of these explanations are incomplete or incorrect
Tony Morris
@dibblego
11. We are looking for an intuition that doesn’t require you to already have expert knowledge.
That is satisfactory, that you feel like you have understood something.
And that’s not wrong.
Have you ever read a monad tutorial on the internet? You’ll find that they meet the first two goals.
Consider burritos.
You don’t need a deep understanding of burritos.
Burritos are satisfactory.
But monads are not burritos. Sorry, they are not.
I am hoping to achieve all three of these.
We seek an intuition that
• Does not require a prior deep understanding of list folds
• Goes far enough to leave us satisfied
• Is not wrong
Tony Morris
@dibblego
12. The way to think about these two different functions is very different.
The intuition for each of them is quite different.
So I am going to be trying to talk about each differently.
First things first
In practice, the foldl and foldr functions are very different
So let us think about and discuss each separately.
Tony Morris
@dibblego
13. Let’s talk about what foldleft does.
It takes a function type f, b to the element type a, to b.
I takes another element b.
And then it takes a list that we are doing a fold on.
I also wrote the C# signature there, if you prefer to read that. I do not.
The foldl function accepts three values
1. f :: b -> a -> b
2. z :: b
3. list :: List a
to get back a value of type b
foldl :: (b -> a -> b) -> b -> List a -> b
B FoldLeft<A,B>(Func<B, A, B>, B, List<A>)
𝑓𝑜𝑙𝑑𝑙 ∷ 𝛽 → 𝛼 → 𝛽 → 𝛽 → 𝛼 → 𝛽
The 𝑓𝑜𝑙𝑑𝑙 signature we saw in part 1.
Tony Morris
@dibblego
14. How does it take these three values to return a value? It does this loop:
Everyone’s heard of a loop, right? They taught that back at loop school. I remember. First
year undergrad: loop school.
So if we look at this loop. Who has written a loop like this before? Everyone has.
?
How does foldl take three values to that return value?
All left folds are loops
f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
Tony Morris
@dibblego
15. And importantly, these (in red) are the three components of the loop that we get to change.
We get to pass in a function, what to do on each iteration of the loop. That’s the b to a to b (b -> a -> b), the f there.
The z there is the b, so that’s what value to start the loop at.
And finally list, the thing that we are looping on, or foldlefting on.
So let’s look at some real code.
All left folds are loops
f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
The foldl function accepts three values
1. f :: b -> a -> b
2. z :: b
3. list :: List a
to get back a value of type b
foldl :: (b -> a -> b) -> b -> List a -> b
Refactor some loops
let’s look at a real code example
Tony Morris
@dibblego
16. In the next slide we are going to see a plus operator enclosed in parentheses. We have already seen + , − , (×), and (↑) in part
1, where we defined them to be curried binary functions and where their definitions made use of infix operators +, −, ×, and ↑.
+ ∷ 𝑵𝒂𝒕 → 𝑵𝒂𝒕 → 𝑵𝒂𝒕
𝑚 + 𝒁𝒆𝒓𝒐 = 𝑚
𝑚 + 𝑺𝒖𝒄𝒄 𝑛 = 𝑺𝒖𝒄𝒄 𝑚 + 𝑛
− ∷ 𝑵𝒂𝒕 → 𝑵𝒂𝒕 → 𝑵𝒂𝒕
𝑚 − 𝒁𝒆𝒓𝒐 = 𝑚
𝑺𝒖𝒄𝒄 𝑚 − 𝑺𝒖𝒄𝒄 𝑛 = 𝑚 − 𝑛
(×) ∷ 𝑵𝒂𝒕 → 𝑵𝒂𝒕 → 𝑵𝒂𝒕
𝑚 × 𝒁𝒆𝒓𝒐 = 𝒁𝒆𝒓𝒐
𝑚 × 𝑺𝒖𝒄𝒄 𝑛 = 𝑚 × 𝑛 + 𝑚
(↑) ∷ 𝑵𝒂𝒕 → 𝑵𝒂𝒕 → 𝑵𝒂𝒕
𝑚 ↑ 𝒁𝒆𝒓𝒐 = 𝑺𝒖𝒄𝒄 𝒁𝒆𝒓𝒐
𝑚 ↑ 𝑺𝒖𝒄𝒄 𝑛 = 𝑚 ↑ 𝑛 × 𝑚
Back then I thought the explanation below would have been
superfluous, but in our current context, I think it is useful.
Enclosing an operator in parentheses converts it to a curried prefix function that can be applied
to its arguments like any other function. For example,
+ 3 4 = 3 + 4
≤ 3 4 = 3 ≤ 4
In particular,
𝑝𝑙𝑢𝑠𝑐 = +
where
𝑝𝑙𝑢𝑠𝑐 ∷ 𝐼𝑛𝑡𝑒𝑔𝑒𝑟 → 𝐼𝑛𝑡𝑒𝑔𝑒𝑟 → 𝐼𝑛𝑡𝑒𝑔𝑒𝑟
𝑝𝑙𝑢𝑠𝑐 𝑥 𝑦 = 𝑥 + 𝑦
17. Let’s add up the numbers in a list. Here is a list of numbers. Add them up.
What am I going to replace z with?
Well? Zero, yes. What about f? Plus? Yes, excellent. That will add up the numbers in the list.
Left fold, given the accumulator through the loop, r, and the element a, add them, start the loop at zero, do it on the list.
This will add up the numbers in a list. And if you eta-reduce that expression there, you end up with just plus. Just do plus
on each iteration of the loop.
All left folds are loops
Let’s sum the integers of a list
All left folds are loops
f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
sum the integers of a list
sum list = foldl (r a -> (+) r a) 0 list
sum = foldl (+) 0
Tony Morris
@dibblego
18. On the previous slide, Tony just said the following: if you eta-reduce that expression there, you end up with plus.
η-reduction is one of the two forms of η-conversion.
η-conversion is adding or dropping of abstraction over a function. It converts between λx.fx and f (whenever x does not
appear free in f).
η-expansion converts f to λx.fx, whereas η-reduction converts λx.fx to f.
Tony performed two consecutive reductions, one from λx.λy.f x y to λx.f x , and another from λx.f x to f.
In his case, x is called r, y is called a, f is (+), and he reduced λr.λa.(+) r a to (+).
sum list = foldl (r a -> (+) r a) 0 list
sum = foldl (+) 0
...you end up with plus “
“if you eta-reduce that expression there,…
η-reduction x 2
19. $ :type (r a -> (+) r a)
(r a -> (+) r a) :: Num a => a -> a -> a
$ :type (+)
(+) :: Num a => a -> a -> a
$ (r a -> (+) r a) 3 4
=> 7
$ (+) 3 4
=> 7
$ foldl (r a -> (+) r a) 0 [2,3,4]
=> 9
$ foldl (+) 0 [2,3,4]
=> 9
scala> :type (r:Int) => (a:Int) => `(+)`(r)(a)
Int => (Int => Int)
scala> :type `(+)`
Int => (Int => Int)
scala> ((r:Int) => (a:Int) => `(+)`(r)(a))(3)(4)
res1: Int = 7
scala> `(+)`(3)(4)
res2: Int = 7
scala> foldl((r:Int) => (a:Int) => `(+)`(r)(a))(0)(List(2,3,4))
res3: Int = 9
scala> foldl(`(+)`)(0)(List(2,3,4))
res4: Int = 9
To help cement the notion of eta-reduction that we saw on the previous slide, and connect it to Scala, on this slide we do
the following:
• compare the types of (r a -> (+) r a) and (+) and see that they are the same
• show that (r a -> (+) r a) and (+) behave the same
To also do that in Scala, we define the equivalent of Haskell’s (+) and foldl ourselves (see bottom of slide).
scala> def foldl[A,B](f: B => A => B)(e: B)(s: List[A]): B = s match {
| case Nil => e
| case x::xs => foldl(f)(f(e)(x))(xs)
| }
def foldl: [A, B](f: B => (A => B))(e: B)(s: List[A]): B
scala> val `(+)` = (x:Int) => (y:Int) => x + y
(+): Int => (Int => Int) = $$Lambda$5001/470155141@690b8d7f
20. What about multiplication?
What do I replace the function f with? What are we going to do on each iteration of the loop?
We are going to do multiplication.
What are we going to start the loop at?
One. Some people say zero. What’s going to happen if I put zero there? Zero. Yes.
One is the identity for multiplication. One is the thing that does nothing to multiplication. One times x gives me x. It did
nothing to x.
multiply the integers of a list
f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
?
Tony Morris
@dibblego
21. There it is. It’s going to multiply the numbers in the list.
And there’s the code. Real Haskell code. How to multiply the numbers in a list.
Left fold: spin on each part of the loop with multiplication, start at 1. Fold left does a loop.
I mean if you open up the source code of fold left you won’t see a loop there. You’ll see al sorts of crazy recursion and you’ll
see a seq or something like that to make it faster.
But all you need to think about is it does a loop, that loop.
multiply the integers of a list
f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
Replace the values in the loop
multiply the integers of a list
product list = foldl (r a -> (*) r a) 1 list
product = foldl (*) 1
all left folds are loops
prod = foldl (*) 1
with
multiplication
start
at 1
spin on
each part
of the loop
Tony Morris
@dibblego
22. How do you reverse a list? This was a trick question yesterday because I had taught everyone about fold right, and then I
said ok, now reverse a list, and they tried to do it using fold right, and it ended up very slow.
Let’s do it with a left fold.
What am I going to replace z with, if I am going to reverse that list?
𝑵𝒊𝒍, the empty list. And on each iteration of that loop I am going to take that element and put it on the front of that list.
That will reverse the list. Left fold through the list, pull the elements off the front and put them on the front of a new list,
𝑵𝒊𝒍, it will come back reversed, in linear time.
all left folds are loops
Let’s reverse a list
reverse a list
f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
Tony Morris
@dibblego
23. There it is. I have a function. There is the list being accumulated r, there is the element of the list a, 𝑪𝒐𝒏𝒔 it, do that in each
iteration of the loop, start at 𝑵𝒊𝒍. This will reverse a list.
That’s the real code.
I once went for a job interview, about twenty years ago, and the interviewer said to me, reverse a list. And I said, OK, what
language. It was actually a C# job, and the guy said, any language you prefer. I said OK, fold left with 𝑪𝒐𝒏𝒔 𝑵𝒊𝒍. And I didn’t
get the job. So I don’t recommend you answer that in that way. But it is correct. That will reverse a list.
reverse a list
list ->
var r = 𝑵𝒊𝒍
foreach(a in list)
r = flipCons(r, a)
return r
flipCons = r a -> 𝑪𝒐𝒏𝒔 a r
reverse a list
reverse list = foldl (r a -> 𝑪𝒐𝒏𝒔 a r) 𝑵𝒊𝒍 list
reverse = foldl (flip 𝑪𝒐𝒏𝒔) 𝑵𝒊𝒍
Tony Morris
@dibblego
24. reverse ∷ α → [α]
reverse = 𝑓𝑜𝑙𝑑𝑟 𝑠𝑛𝑜𝑐
𝒘𝒉𝒆𝒓𝒆 𝑠𝑛𝑜𝑐 𝑥 𝑥𝑠 = 𝑥𝑠 ⧺ [𝑥]
reverse′ ∷ α → [α]
reverse′ = 𝑓𝑜𝑙𝑑𝑙 𝑐𝑜𝑛𝑠
𝒘𝒉𝒆𝒓𝒆 𝑐𝑜𝑛𝑠 𝑥𝑠 𝑥 = 𝑥 : 𝑥𝑠
reverse′ takes time proportional to 𝑛 on a list of
length 𝑛, while reverse takes time proportional to 𝑛2
reverse = foldl (flip 𝑪𝒐𝒏𝒔) 𝑵𝒊𝒍
Note the order of the arguments to 𝑐𝑜𝑛𝑠; we have 𝑐𝑜𝑛𝑠 = 𝑓𝑙𝑖𝑝 (∶),
where the standard function 𝑓𝑙𝑖𝑝 is defined by 𝑓𝑙𝑖𝑝𝑓 𝑥 𝑦 = 𝑓 𝑦 𝑥.
The function reverse′ , reverses a finite list.
Here is the definition of reverse that Tony showed us
We have already seen it in part 1
Tony said that defining reverse using foldr ends up
very slow, which we have also already seen in part 1
25. What about the length of a list? What are we going to do? We are going to start the loop at zero, and for each of the
accumulators, the accumulator r, we are going to ignore the element a, and just add one to r. That will compute the length
of a list.
So, the function plus1, given r, ignore a, do r + 1, do that on each spin of that loop, it will compute the length of the list.
There’s the code. I essentially read this word here (foldl) as do a loop. That’s how I like to think about it. On each iteration
of the loop, do that, start there. That will compute the length of a list. This is just a point-free way of writing that same
function. const means ignore the element, and then do plus1. On each iteration.
all left folds are loops
Let’s compute the length of a list
length of a list
list ->
var r = 0
foreach(a in list)
r = plus1(r, a)
return r
plus1 = r a -> r + 1
length of a list
length list = foldl (r a -> r + 1) 0 list
length = foldl (const . (+ 1)) 0
Tony Morris
@dibblego
26. If I said to you, take all of the loops that you have written and refactor out all of their differences, you’ll end up with fold
left. They are exactly this loop. That is to say, I don’t need a little footnote here to say, “just kidding, it is not quite precise”.
It is exactly that loop. Which means that any question we might ask about a left fold we can also ask about that loop, and
we’ll get the same answer.
For example, will that loop ever work on an infinite list? Nope. An infinite list, by the way, is one that doesn’t have 𝑵𝒊𝒍. It is
just 𝑪𝒐𝒏𝒔 all the way to infinity. If I put that into a left fold or into that loop, it just will never give me an answer. It will sit
there and heat up the world a bit more.
It is easy to transfer this information because you probably have already heard of loops. I have used your existing
knowledge to transfer this information. Left fold is a loop.
refactoring, intuition
• a left fold is what you would write if I insisted you remove
all duplication from your loops
• all left folds are exactly this loop
• any question we might ask about a left fold, can be asked
about this loop.
some observations
• a left fold will never work on an infinite list
• a correct intuition for left folds is easy to build on existing
programming knowledge (loop).
Folding to the left does a loop
Tony Morris
@dibblego
27. 𝑓𝑜𝑙𝑑𝑙 ∷ 𝛽 → 𝛼 → 𝛽 → 𝛽 → 𝛼 → 𝛽
𝑓𝑜𝑙𝑑𝑙 𝑓 𝑒 = 𝑒
𝑓𝑜𝑙𝑑𝑙 𝑓 𝑒 𝑥: 𝑥𝑠 = 𝑓𝑜𝑙𝑑𝑙 𝑓 𝑓 𝑒 𝑥 𝑥𝑠
sum the integers of a list
sum list = foldl (r a -> (+) r a) 0 list
sum = foldl (+) 0
multiply the integers of a list
product list = foldl (r a -> (*) r a) 1 list
product = foldl (*) 1
reverse a list
reverse list = foldl (r a -> 𝑪𝒐𝒏𝒔 a r) 𝑵𝒊𝒍 list
reverse = foldl (flip 𝑪𝒐𝒏𝒔) 𝑵𝒊𝒍
length of a list
length list = foldl (r a -> r + 1) 0 list
length = foldl (const . (+ 1)) 0
reverse ∷ α → [α]
reverse = 𝑓𝑜𝑙𝑑𝑙 𝑐𝑜𝑛𝑠
𝒘𝒉𝒆𝒓𝒆 𝑐𝑜𝑛𝑠 𝑥𝑠 𝑥 = 𝑥 : 𝑥𝑠
𝑠𝑢𝑚 ∷ [𝑰𝒏𝒕] → 𝑰𝒏𝒕
𝑠𝑢𝑚 = 𝑓𝑜𝑙𝑑𝑙 + 0
𝑙𝑒𝑛𝑔𝑡ℎ ∷ [α] → 𝑰𝒏𝒕
𝑙𝑒𝑛𝑔𝑡ℎ = 𝑓𝑜𝑙𝑑𝑙 𝑝𝑙𝑢𝑠𝑜𝑛𝑒 0,
𝒘𝒉𝒆𝒓𝒆 𝑝𝑙𝑢𝑠𝑜𝑛𝑒 𝑛 𝑥 = 𝑛 + 1
𝑝𝑟𝑜𝑑 ∷ [𝑰𝒏𝒕] → 𝑰𝒏𝒕
𝑝𝑟𝑜𝑑 = 𝑓𝑜𝑙𝑑𝑙 (×) 1
foldl :: (b -> a -> b) -> b -> List a -> b
foldl = f z list ->
var r = z
foreach(a in list)
r = f(r, a)
return r
all left folds are loops
𝑓𝑜𝑙𝑑𝑙 can be seen as a loop because it is a
tail-recursive function.
On the left are Tony’s function
definitions, and on the right are the
definitions we saw in parts 1 and 2.
28. Folding to the left does a loop. The end.
For right folds there is no existing thing that I can use to transfer the information, you just simply need to commit to the
definition of a list, which is, 𝑵𝒊𝒍 or 𝑪𝒐𝒏𝒔. So let’s commit to that right now. That’s what a list is.
The fold right function.
Well, it takes a function, a to b to b (a is the element type in the list), and then it takes a b, and it takes a list, and it returns
a b. There it is, written in Haskell. There is it written in, Java, I think, I don’t know. One of those languages.
What does it do? How does it take that function, that b, and that list and give me a b?
Folding to the left does a loop
The foldr function accepts three values
1. f :: a -> b -> b
2. z :: b
3. list :: List a
to get back a value of type b
foldr :: (a -> b -> b) -> b -> List a -> b
B FoldRight<A,B>(Func<A, B, B>, B, List<A>)
The foldl function accepts three values
1. f :: b -> a -> b
2. z :: b
3. list :: List a
to get back a value of type b
foldl :: (b -> a -> b) -> b -> List a -> b
B FoldLeft<A,B>(Func<B, A, B>, B, List<A>)
?
How does foldr take three values to that return value?
Tony Morris
@dibblego
29. It performs constructor replacement. So, constructors, remember, are 𝑵𝒊𝒍 and 𝑪𝒐𝒏𝒔, they are the two things that
construct lists. The expression fold right with the function f, z on a list, will go through that list, in no particular order,
and replace every 𝑪𝒐𝒏𝒔 with f, and 𝑵𝒊𝒍 with z. If it sees a 𝑵𝒊𝒍, which it might not, because it might be infinite.
So if we take this list A, B, C, D, and I fold right with f and z on that list, I’ll get back whatever value is replacing 𝑪𝒐𝒏𝒔
with f and 𝑵𝒊𝒍 with z, whatever that is.
So if A, B, C and D are all numbers and we want to add them up, I can replace f with plus, and z with zero, and it will add
them all up.
constructor replacement
The foldr function performs constructor replacement.
The expression foldr f z list replaces in list:
• Every occurrence of 𝑪𝒐𝒏𝒔 (:) with f.
• Any occurrence of 𝑵𝒊𝒍 [] with z1.
1 The 𝑵𝒊𝒍 constructor may be absent – i.e. the list is an infinite list of 𝑪𝒐𝒏𝒔.
constructor replacement?
• Suppose list = 𝑪𝒐𝒏𝒔 A (𝑪𝒐𝒏𝒔 B (𝑪𝒐𝒏𝒔 C (𝑪𝒐𝒏𝒔 D 𝑵𝒊𝒍)))
• The expression foldr f z list
• produces f A (f B (f C (f D z)))
Tony Morris
@dibblego
30. constructor replacement
The foldr function performs constructor replacement.
The expression foldr f z list replaces in list:
• Every occurrence of 𝑪𝒐𝒏𝒔 (:) with f.
• Any occurrence of 𝑵𝒊𝒍 [] with z1.
1 The 𝑵𝒊𝒍 constructor may be absent – i.e. the list is an infinite list of 𝑪𝒐𝒏𝒔.
2 The fold operator
The fold operator has its origins in recursion theory (Kleene, 1952), while the use of fold as
a central concept in a programming language dates back to the reduction operator of APL
(Iverson, 1962), and later to the insertion operator of FP (Backus, 1978). In Haskell, the fold
operator for lists can be defined as follows:
𝑓𝑜𝑙𝑑 :: 𝛼 → 𝛽 → 𝛽 → 𝛽 → 𝛼 → 𝛽
𝑓𝑜𝑙𝑑 𝑓 𝑣 = 𝑣
𝑓𝑜𝑙𝑑 𝑓 𝑣 𝑥 ∶ 𝑥𝑠 = 𝑓 𝑥 𝑓𝑜𝑙𝑑 𝑓 𝑣 𝑥𝑠
That is, given a function f of type 𝛼 → 𝛽 → 𝛽 and a value 𝑣 of type 𝛽, the function
𝑓𝑜𝑙𝑑 𝑓 𝑣 processes a list of type 𝛼 to give a value of type 𝛽 by replacing the nil
constructor at the end of the list by the value 𝑣, and each cons constructor ∶ within
the list by the function 𝑓. In this manner, the 𝑓𝑜𝑙𝑑 operator encapsulates a simple pattern
of recursion for processing lists, in which the two constructors for lists are simply
replaced by other values and functions.
Consider the following definition of a function ℎ :
ℎ [ ] = 𝑒
ℎ 𝑥: 𝑥𝑠 = 𝑥 ⊕ ℎ 𝑥𝑠
The function ℎ works by taking a list, replacing [ ] by 𝑒 and ∶ by ⊕, and evaluating
the result. For example, ℎ converts the list
𝑥1 ∶ (𝑥2 ∶ 𝑥3 ∶ 𝑥4 ∶ )
to the value
𝑥1 ⊕ (𝑥2 ⊕ (𝑥3 ⊕ 𝑥4 ⊕ 𝑒 ))
Since ∶ associates to the right, there is no need to put in parentheses in the first
expression. However, we do need to put in parentheses in the second expression
because we do not assume that ⊕ associates to the right.
The pattern of definition given by ℎ is captured in a function 𝑓𝑜𝑙𝑑𝑟 (pronounced ‘fold
right’) defined as follows:
𝑓𝑜𝑙𝑑𝑟 ∷ 𝛼 → 𝛽 → 𝛽 → 𝛽 → 𝛼 → 𝛽
𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 = 𝑒
𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 𝑥: 𝑥𝑠 = 𝑓 𝑥 𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 𝑥𝑠
Here on the right is Tony’s explanation that foldr does
constructor replacement, and below are the explanations
we came across in Part 1.
31. Let’s multiply them. So here is a list of numbers, 4, 5, 6, 7. I am going to replace 𝑪𝒐𝒏𝒔 with multiplication and 𝑵𝒊𝒍 with one.
And now, that will multiply the numbers in a list.
Fold right did constructor replacement.
multiply the integers of a list
Supposing
list = 𝑪𝒐𝒏𝒔 4 (𝑪𝒐𝒏𝒔 5 (𝑪𝒐𝒏𝒔 6 (𝑪𝒐𝒏𝒔 7 𝑵𝒊𝒍)))
?
multiply the integers of a list
• let 𝑪𝒐𝒏𝒔 = (*)
• let 𝑵𝒊𝒍 = 1
multiply the integers of a list
Supposing
list = (*) 4 ((*) 5 ((*) 6 ((*) 7 1)))
product list = foldr (*) 1 list
product = foldr (*) 1
Tony Morris
@dibblego
32. The important thing about fold right to recognize, is that it doesn’t do it in any particular order. There is an associativity
order, but there is not an execution order. So that is to say, some people might say to me, fold right starts at the right side
of the list. This can’t be true, because I am going to be passing in an infinite list, which doesn’t have a right side, and I am
going to get an answer. If it started at the right, it went a really long way, and it is still going. So that is what I should see if
that statement is true, but I don’t see that. It associates to the right, it didn’t start executing from the right. It’s a subtle
difference.
What if I have a list of booleans and I want to and them all up? What am I going to replace 𝑵𝒊𝒍 with? Not 99. True. Yes.
So if I have the above list, and I replace 𝑵𝒊𝒍 with True and 𝑪𝒐𝒏𝒔 with (&&), like this
It will and (&&) them all up
right folds replace constructors
Let’s and (&&) the booleans of a list.
and (&&) the booleans of a list
Supposing
list = 𝑪𝒐𝒏𝒔 True (𝑪𝒐𝒏𝒔 True (𝑪𝒐𝒏𝒔 False (𝑪𝒐𝒏𝒔 True 𝑵𝒊𝒍)))
and (&&) the booleans of a list
• let 𝑪𝒐𝒏𝒔 = (&&)
• let 𝑵𝒊𝒍 = True
Tony Morris
@dibblego
33. So there is the code. Right fold replacing 𝑪𝒐𝒏𝒔 with (&&) and 𝑵𝒊𝒍 with True. It doesn’t do it in any order. I could have an
infinite list of booleans. Suppose I had an infinite list of booleans and it started at False. 𝑪𝒐𝒏𝒔 False something. And I
said foldr (&&) True. I should get back False. And I do. So clearly it didn’t start from the right. It never went there. It
just saw the False and stopped.
How about appending two lists?
Here is a list. Here is a second list. How do I append them?
Do you agree with me that I am going to go through this first list and replace 𝑪𝒐𝒏𝒔 with 𝑪𝒐𝒏𝒔 and 𝑵𝒊𝒍 with the second
list? Who agrees with me on that? That’s how you append two lists. Just an intuition for appending two lists. I take the first
list, replace 𝑪𝒐𝒏𝒔 with 𝑪𝒐𝒏𝒔 and 𝑵𝒊𝒍 with the other list, they are now appended.
and (&&) the booleans of a list
Supposing
list = (&&) True ((&&) True ((&&) False ((&&) True True)))
conjunct list = foldr (&&) True list
conjunct = foldr (&&) True
right folds replace constructors
Let’s append two lists.
append two lists
Supposing
list1 = 𝑪𝒐𝒏𝒔 A (𝑪𝒐𝒏𝒔 B (𝑪𝒐𝒏𝒔 C (𝑪𝒐𝒏𝒔 D 𝑵𝒊𝒍)))
list2 = 𝑪𝒐𝒏𝒔 E (𝑪𝒐𝒏𝒔 F (𝑪𝒐𝒏𝒔 G (𝑪𝒐𝒏𝒔 H 𝑵𝒊𝒍)))
Tony Morris
@dibblego
34. So now that you know that you should not be afraid when you see the code. I am going to go through this first list and
replace 𝑪𝒐𝒏𝒔 with 𝑪𝒐𝒏𝒔, that is leave it alone, and I am going to pick up this entire list2 and smash it straight over the
𝑵𝒊𝒍. And that will be appended.
So here is the code.
Go in list1, replace 𝑪𝒐𝒏𝒔 with 𝑪𝒐𝒏𝒔 and 𝑵𝒊𝒍 with list2. This will append list1 and list2.
Sometimes I show people this code and they get scared. Wow, hang on, what is going on here? I am used to loops and things.
That’s how you append lists. Or go to the pointer at the end and update it to the other list, something crazy like that.
But if you get an intuition for fold right, which is doing constructor replacement, it is pretty straightforward, right? 𝑪𝒐𝒏𝒔
with 𝑪𝒐𝒏𝒔 and 𝑵𝒊𝒍 with list2. Of course it is going to append the two lists (The second definition is just a point-free form).
You might choose to say that at your next job interview. Hey man, append two lists, ok, flip (foldr 𝑪𝒐𝒏𝒔). Tell me how it
goes.
append two lists
• let 𝑪𝒐𝒏𝒔 = 𝑪𝒐𝒏𝒔
• let 𝑵𝒊𝒍 = list2
append two lists
Supposing
list1 = 𝑪𝒐𝒏𝒔 A (𝑪𝒐𝒏𝒔 B (𝑪𝒐𝒏𝒔 C (𝑪𝒐𝒏𝒔 D 𝑵𝒊𝒍)))
list2 = 𝑪𝒐𝒏𝒔 E (𝑪𝒐𝒏𝒔 F (𝑪𝒐𝒏𝒔 G (𝑪𝒐𝒏𝒔 H 𝑵𝒊𝒍)))
append list1 list2 = foldr 𝑪𝒐𝒏𝒔 list2 list1
append = flip (foldr 𝑪𝒐𝒏𝒔)
Tony Morris
@dibblego
35. append list1 list2 = foldr 𝑪𝒐𝒏𝒔 list2 list1
append = flip (foldr 𝑪𝒐𝒏𝒔)
We have already come across the function in part 1, where Richard Bird called it concatenation, and defined it recursively
(⧺) ∷ [α] → [α] → [α]
⧺ 𝑦𝑠 = 𝑦𝑠
𝑥: 𝑥𝑠 ⧺ 𝑦𝑠 = 𝑥 ∶ (𝑥𝑠 ⧺ 𝑦𝑠)
Concatenation takes two lists, both of
the same type, and produces a third
list, again of the same type. assert( concatenate(List(1,2,3))(List(4,5)) == List(1,2,3,4,5) )
def concatenate[A]: List[A] => List[A] => List[A] =
xs => ys => xs match {
case Nil => ys
case x :: xs => x :: concatenate(xs)(ys)
}
Then in TUEF we saw the function defined in terms of 𝑓𝑜𝑙𝑑𝑟
(⧺) ∷ [α] → [α] → [α]
⧺ 𝑦𝑠 = 𝑓𝑜𝑙𝑑𝑟 ∶ 𝑦𝑠
def concatenate[A]: List[A] => List[A] => List[A] = {
def cons: A => List[A] => List[A] =
x => xs => x :: xs
xs => ys => foldr(cons)(ys)(xs)
}
Here is Tony’s definition of the append function.
36. def concatenate[A]: List[A] => List[A] => List[A] = {
def cons: A => List[A] => List[A] =
x => xs => x :: xs
xs => ys => foldr(cons)(ys)(xs)
}
def foldr[A,B](f: A => B => B)(e: B)(s: List[A]): B = s match {
case Nil => v
case x::xs => f(x)(foldr(f)(e)(xs))
}
(⧺) ∷ [α] → [α] → [α]
⧺ 𝑦𝑠 = 𝑓𝑜𝑙𝑑𝑟 ∶ 𝑦𝑠
𝑓𝑜𝑙𝑑𝑟 ∷ 𝛼 → 𝛽 → 𝛽 → 𝛽 → 𝛼 → 𝛽
𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 = 𝑒
𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 𝑥: 𝑥𝑠 = 𝑓 𝑥 𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 𝑥𝑠
def foldr[A,B](f: A => B => B)(v: B)(s: List[A]): B = s match {
case 𝑵𝒊𝒍 => v
case 𝑪𝒐𝒏𝒔(x,xs) => f(x)(foldr(f)(v)(xs))
}
def flip[A,B,C]: (A => B => C) => (B => A => C) =
f => b => a => f(a)(b)
def append[A]: 𝑳𝒊𝒔𝒕[A] => 𝑳𝒊𝒔𝒕[A] => 𝑳𝒊𝒔𝒕[A] =
flip(foldr((𝑪𝒐𝒏𝒔[A] _).curried))
Let’s take Tony’s two definitions of append, and translate them into Scala. Unlike
the Scala concatenate function on the previous slide, which is repeated below,
and which relies on the foldr definition to its right, Tony’s definitions use 𝑪𝒐𝒏𝒔.
append list1 list2 = foldr 𝑪𝒐𝒏𝒔 list2 list1
append = flip (foldr 𝑪𝒐𝒏𝒔)
So let’s first modify the Scala version
of 𝑓𝑜𝑙𝑑𝑟 to use 𝑵𝒊𝒍 and 𝑪𝒐𝒏𝒔
sealed trait 𝑳𝒊𝒔𝒕[+A]
case class 𝑪𝒐𝒏𝒔[+A](head: A, tail: 𝑳𝒊𝒔𝒕[A]) extends 𝑳𝒊𝒔𝒕[A]
case object 𝑵𝒊𝒍 extends 𝑳𝒊𝒔𝒕[Nothing]
def append[A]: 𝑳𝒊𝒔𝒕[A] => 𝑳𝒊𝒔𝒕[A] => 𝑳𝒊𝒔𝒕[A] =
xs => ys => foldr[A, 𝑳𝒊𝒔𝒕[A]]((𝑪𝒐𝒏𝒔[A] _).curried)(ys)(xs)
append = flip (foldr 𝑪𝒐𝒏𝒔)
We can now write the Scala equivalent of Tony’s first
definition of append
And if we write a Scala version of flip, we can then also
translate into Scala Tony’s second definition of append.
append list1 list2 = foldr 𝑪𝒐𝒏𝒔 list2 list1 NOTE: (𝑪𝒐𝒏𝒔[A] _) has type (A, List[A]) => List[A], whereas
(𝑪𝒐𝒏𝒔[A] _).curried) has type A => List[A] => List[A]
37. append list1 list2 = foldr 𝑪𝒐𝒏𝒔 list2 list1
I don’t know about you, but when I see append implemented so simply and elegantly in terms of fold right, I can’t help
wanting to see how append looks like when defined using fold left. The quickest way I can think of, for coming up with
such a definition is to apply the third duality theorem of fold.
Here again is Tony’s definition of the append function.
Third duality theorem. For all finite lists 𝑥𝑠,
𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 𝑥𝑠 = 𝑓𝑜𝑙𝑑𝑙 𝑓𝑙𝑖𝑝 𝑓 𝑒 (𝑟𝑒𝑣𝑒𝑟𝑠𝑒 𝑥𝑠)
𝒘𝒉𝒆𝒓𝒆 𝑓𝑙𝑖𝑝 𝑓 𝑥 𝑦 = 𝑓 𝑦 𝑥
And here again is the
third duality theorem.
Let’s use the theorem the other way round. Let’s take the above definition of append in terms
of fold right, and do the following:
• flip the first parameter of fold right
• reverse the third parameter of fold right
• replace fold right with fold left
append list1 list2 = foldl scon list2 (reverse list1)
where scon xs x = 𝑪𝒐𝒏𝒔 x xs
38. What about mapping a function on a list? So who’s heard of the map function? Or who’s never heard of it? Everyone has.
We have a list, and for each of the elements, I want to run a function on that element, to make a new list. Like I might have
a list of numbers and I want to add ten to all of the numbers, I want to map + 10 on that list.
So here is my list
What do I want to replace 𝑪𝒐𝒏𝒔 with? Given the function f, do you agree that I want to say, 𝑪𝒐𝒏𝒔, f of A, 𝑪𝒐𝒏𝒔, f of B,
𝑪𝒐𝒏𝒔, f of C, and D and then 𝑵𝒊𝒍? That’s what map does. I want to replace 𝑪𝒐𝒏𝒔 with f and then 𝑪𝒐𝒏𝒔. And 𝑵𝒊𝒍 with 𝑵𝒊𝒍.
So, given x I want to call f, then 𝑪𝒐𝒏𝒔. And 𝑵𝒊𝒍 with 𝑵𝒊𝒍. This will map the function f on a list.
right folds replace constructors
Let’s map a function on a list
map a function (f) on a list
Supposing
list = 𝑪𝒐𝒏𝒔 A (𝑪𝒐𝒏𝒔 B (𝑪𝒐𝒏𝒔 C (𝑪𝒐𝒏𝒔 D 𝑵𝒊𝒍)))
?
map a function (f) on a list
• let 𝑪𝒐𝒏𝒔 = x -> 𝑪𝒐𝒏𝒔(fx)
• let 𝑵𝒊𝒍 = 𝑵𝒊𝒍
Tony Morris
@dibblego
39. So there is the code. It’s not that scary now, is it? That’s how you map a function on a list. We replace 𝑪𝒐𝒏𝒔 with (x ->
𝑪𝒐𝒏𝒔(f x)), and 𝑵𝒊𝒍 with 𝑵𝒊𝒍. We have mapped a function on a list.
Once I had to write mapping a function on a list in Java. This was 15 years ago. I didn’t use fold right. This is just like,
footnote: caution. If you use fold right in Java, what’s going to happen? Stack overflow. Yes, because fold right is
recursive. For every element in the list, it’s building up a stack frame. So you can imagine my disappointment when I
called fold right on the JVM, with a list of 10,000 numbers, or whatever it was, and it just said: Stack overflow – have a
nice day. Because the JVM I used to use, this is a long time ago, was the IBM JVM.
It did tail-call optimisation, but it didn’t optimise this one because it wasn’t in tail position. And it didn’t work on infinite
lists either. I had to make it a heap list. So I am just letting you know, that all of this sounds great, but if you run out the
door right now and say, ‘I am going to do it in Java,’ caution. The same is true for Python, C#, I have tried it: Stack overflow.
This little operator here, the dot, is function composition. It takes two functions and glues them together to make a new
function. So I’ll give you a bit of an intuition for function composition. I read it from right to left. Call f and then call 𝑪𝒐𝒏𝒔.
So wherever we are in the list, somewhere in a 𝑪𝒐𝒏𝒔 cell, which means it has an element right next to it, call f on that
element, and then do 𝑪𝒐𝒏𝒔. And replace 𝑵𝒊𝒍 with 𝑵𝒊𝒍.
I wonder what would happen if you said that in a job interview. I should try that. Someone will say map a function on a list
and they are waiting for me to say for loop, and I go, no no, fold right.
map a function (f) on a list
Supposing
consf x = 𝑪𝒐𝒏𝒔 (f x)
list = consf A (consf B (consf C (consf D 𝑵𝒊𝒍)))
map f list = foldr (x -> 𝑪𝒐𝒏𝒔(f x)) 𝑵𝒊𝒍 list
map f = foldr (𝑪𝒐𝒏𝒔 . f) 𝑵𝒊𝒍
Tony Morris
@dibblego
40. As Tony said, it was a long time ago that he experienced that stack overflow when
calling foldRight on a very long list.
As we saw in Part 2, in more recent years, the foldRight function of List has been
redefined to take advantage of the third duality theorem of fold, i.e. it is now
defined in terms of foldLeft, in that it first reverses the list that it is passed, and then
does that same loop that foldLeft would do, except that there is no need to do any
function flipping: the loop can just apply the given function as it stands.
So no more stack overflows.
Third duality theorem. For all finite lists 𝑥𝑠,
𝑓𝑜𝑙𝑑𝑟 𝑓 𝑒 𝑥𝑠 = 𝑓𝑜𝑙𝑑𝑙 𝑓𝑙𝑖𝑝 𝑓 𝑒 (𝑟𝑒𝑣𝑒𝑟𝑠𝑒 𝑥𝑠)
𝒘𝒉𝒆𝒓𝒆 𝑓𝑙𝑖𝑝 𝑓 𝑥 𝑦 = 𝑓 𝑦 𝑥
41. What about flattening a list of lists? So we have a list, and each element is itself a list, and we
want to flatten it down. What am I going to replace 𝑪𝒐𝒏𝒔 with? Any ideas? append, the
function we just wrote. Go through each 𝑪𝒐𝒏𝒔 and replace it with the function that appends
two lists, and 𝑵𝒊𝒍 with 𝑵𝒊𝒍. That will flatten the list of lists.
There is the code. fold right append 𝑵𝒊𝒍.
fold right does constructor replacement.
right folds replace constructors
Let’s flatten a list of lists
flatten a list of lists
• let 𝑪𝒐𝒏𝒔 = append
• let 𝑵𝒊𝒍 = 𝑵𝒊𝒍
flatten list = foldr append 𝑵𝒊𝒍 list
flatten = foldr append 𝑵𝒊𝒍
Tony Morris
@dibblego
42. concat ∷ [ α ] → [α]
concat = 𝒇𝒐𝒍𝒅𝒓 (⧺) [ ]
concat ∷ [ α ] → [α]
concat =
concat 𝑥𝑠: 𝑥𝑠𝑠 = 𝑥𝑠 ⧺ 𝑐𝑜𝑛𝑐𝑎𝑡 𝑥𝑠𝑠
𝑔 = 𝑣 ⟺ 𝑔 = 𝑓𝑜𝑙𝑑𝑟 𝑓 𝑣
𝑔 𝑥 ∶ 𝑥𝑠 = 𝑓 𝑥 𝑔 𝑥𝑠
universal property of 𝒇𝒐𝒍𝒅𝒓
𝑠𝑢𝑚 = 𝑓𝑜𝑙𝑑 + 0
𝑠𝑢𝑚 ∷ 𝐼𝑛𝑡 → 𝐼𝑛𝑡
𝑠𝑢𝑚 = 0
𝑠𝑢𝑚 𝑥 ∶ 𝑥𝑠 = 𝑥 + 𝑠𝑢𝑚 𝑥𝑠
Tony’s definition of flatten is the same as that of the concat function we saw in Part 1.
flatten :: [[a]]->[a]
flatten = foldr append 𝑵𝒊𝒍
For comparison, here is the other definition of concat that we saw in Part 1, the one that does not use 𝒇𝒐𝒍𝒅𝒓.
Richard Bird says in his book that the above definition of concat is exactly what we would get from the definition
concat = 𝒇𝒐𝒍𝒅𝒓 (⧺) [ ] by eliminating the 𝒇𝒐𝒍𝒅𝒓.
𝑚𝑎𝑝 ∷ 𝛼 → 𝛽 → 𝛼 → 𝛽
𝑚𝑎𝑝 𝑓 =
𝑚𝑎𝑝 𝑓 𝑥 ∶ 𝑥𝑠 = 𝑓 𝑥 ∶ 𝑚𝑎𝑝 𝑓 𝑥𝑠
𝑚𝑎𝑝 𝑓 = 𝑓𝑜𝑙𝑑 𝜆𝑥 𝑦𝑠 → 𝑓 𝑥 ∶ 𝑦𝑠 [ ]
And in Part 1 we saw Graham Hutton explain how the universal
property of 𝒇𝒐𝒍𝒅𝒓 can be used to go from a function definition that
doesn’t use 𝒇𝒐𝒍𝒅𝒓 to a definition that does (and also to go the
other way round).
43. foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f e [] = e
foldr f e (x:xs) = f x (foldr f e xs)
foldr (:) ys [] = ys
foldr (:) ys (x:xs) = x : (foldr (:) ys xs)
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x : (append xs ys)
replace f with (:)
replace e with ys
append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xsFor what it is worth, on this slide I just want to show that it looks like in simple cases, like in the case of the append
function, it seems possible, and easy enough, to eliminate foldr using some informal code transformations.
replace foldr (:) with append
swap append parameters
append xs ys = foldr (:) ys xs
44. As Richard Bird points out in his book, since ⧺ (i.e.
append) is associative with unit [ ], thanks to the
first duality theorem of fold, concat can also be
defined using 𝒇𝒐𝒍𝒅𝒍.
concat ∷ [ α ] → [α]
concat = 𝒇𝒐𝒍𝒅𝒓 (⧺) [ ]
Now back to Tony’s definition of flatten,
or as it was called in Part 1, concat.
flatten :: [[a]]->[a]
flatten = foldr append 𝑵𝒊𝒍
First duality theorem. Suppose ⊕ is associative with unit 𝑒. Then
𝑓𝑜𝑙𝑑𝑟 ⊕ 𝑒 𝑥𝑠 = 𝑓𝑜𝑙𝑑𝑙 ⊕ 𝑒 𝑥𝑠
For all finite lists 𝑥𝑠.
Richard Bird also observes that eliminating 𝒇𝒐𝒍𝒅𝒍 from the definition of concat
leads to the following program.
concat ∷ [ α ] → [α]
concat = 𝒇𝒐𝒍𝒅𝒍 (⧺) [ ]
concat′ ∷ α → [α]
concat′ 𝑥𝑠𝑠 = 𝑎𝑐𝑐𝑢𝑚 𝑥𝑠𝑠
𝑎𝑐𝑐𝑢𝑚 𝑤𝑠 = 𝑤𝑠
𝑎𝑐𝑐𝑢𝑚 𝑤𝑠 𝑥𝑠 ∶ 𝑥𝑠𝑠 = 𝑎𝑐𝑐𝑢𝑚 𝑤𝑠 ⧺ 𝑥𝑠 𝑥𝑠𝑠
reverse′ ∷ α → [α]
reverse′ = 𝑓𝑜𝑙𝑑𝑙 𝑐𝑜𝑛𝑠
𝒘𝒉𝒆𝒓𝒆 𝑐𝑜𝑛𝑠 𝑥𝑠 𝑥 = 𝑥 : 𝑥𝑠
reverse′ ∷ α → [α]
reverse′ 𝑥𝑠 = 𝑎𝑐𝑐𝑢𝑚 𝑥𝑠
𝑎𝑐𝑐𝑢𝑚 𝑤𝑠 = 𝑤𝑠
𝑎𝑐𝑐𝑢𝑚 𝑤𝑠 𝑥 ∶ 𝑥𝑠 = 𝑎𝑐𝑐𝑢𝑚 𝑥 ∶ 𝑤𝑠 𝑥𝑠
Similarly, if we eliminate 𝒇𝒐𝒍𝒅𝒍
from the definition of reverse′
We get this program
So eliminating 𝒇𝒐𝒍𝒅𝒍 leads to a
tail-recursive function definition
that uses an accumulator.
45. Sergei Winitzki
sergei-winitzki-11a6431
How did we rewrite the code of lengthS to obtain the tail-recursive code of lengthT?
An important difference between lengthS and lengthT is the additional argument, res, called the
accumulator argument. This argument is equal to an intermediate result of the computation.
The next intermediate result (1 + res) is computed and passed on to the next recursive call via the
accumulator argument. In the base case of the recursion, the function now returns the accumulated result,
res, rather than 0, because at that time the computation is finished.
Rewriting code by adding an accumulator argument to achieve tail recursion is called the accumulator
technique or the “accumulator trick”.
@tailrec def lengthT(s: Seq[Int], res: Int): Int =
if (s.isEmpty) res
else lengthT(s.tail, 1 + res)
def lengthS(s: Seq[Int]): Int =
if (s.isEmpty) 0
else 1 + lengthS(s.tail)
As Sergei Winitzki explained in Part 2, introducing an accumulator in
order to achieve tail recursion is known as the accumulator trick.
lengthT(Seq(1,2,3), 0)
= lengthT(Seq(2,3), 1 + 0) // = lengthT(Seq(2,3), 1)
= lengthT(Seq(3), 1 + 1) // = lengthT(Seq(3), 2)
= lengthT(Seq(), 1 + 2) // = lengthT(Seq(), 3)
= 3
46. Again, for what it is worth, on this slide I
just want to show that it looks like in
simple cases, like in the case of the
append function, it seems possible, and
easy enough, to eliminate foldl using
some informal code transformations.
replace f with scon
replace e with ys
append :: [a] -> [a] -> [a]
append xs ys = foldl scon ys (reverse xs)
where scon xs x = x : xs
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f e [] = e
foldl f e (x:xs) = foldl f (f e x) xs
foldl scon ys [] = ys
foldl scon ys (x:xs) = foldl scon (scon ys x) xs
replace foldl scon with accum
inline remaining invocation of scon
accum ys [] = ys
accum ys (x:xs) = accum (x:ys) xs
define append in terms of accum
append xs ys = accum ys (reverse xs)
47. In both part 1 and in this part, we have come across the notion that sometimes it is
more efficient to implement a function using a right fold, and at other times, it is
more efficient to implement it using a left fold.
An effective way of comparing the performance of different definitions of a function
is to carry out asymptotic analysis and then express the performance of each
definition using the associated notation, i.e. 𝑂-notation, 𝛺–notation and 𝛩-
notation.
The next four slides consist of a quick introduction to (refresher of) asymptotic
analysis, and consists of extracts from Richard Bird’s book.
48. 7.2 Asymptotic Analysis
In general, one is less interested in estimating the cost of evaluating a particular expression than in comparing the
performance of one definition of a function with another. For example, consider the following two programs for
reversing a list:
reverse =
reverse 𝑥 ∶ 𝑥𝑠 = 𝑟𝑒𝑣𝑒𝑟𝑠𝑒 𝑥𝑠 ⧺ [𝑥]
reverse′ = 𝑓𝑜𝑙𝑑𝑙 𝑝𝑟𝑒𝑓𝑖𝑥 𝒘𝒉𝒆𝒓𝒆 𝑝𝑟𝑒𝑓𝑖𝑥 𝑥𝑠 𝑥 = 𝑥 : 𝑥𝑠
It was claimed in section 4.5 that the second program is more efficient than the former, taking at most a number of
steps proportional to 𝑛 on a list of length 𝑛, while the first program takes 𝑛2 steps. The aim of this section is to show
how to make such claims more precise and to justify them.
7.2.1 Order notation
Given two functions 𝑓 and 𝑔 on the natural numbers, we say that 𝑓 is of order at most 𝑔, and write 𝑓 = 𝑂 𝑔 if
there is a positive constant C and natural number n0 such that 𝑓 𝑛 ≤ C 𝑔(𝑛) for all 𝑛 ≥ n0.
In other words, 𝑓 is bounded above by some constant times 𝑔 for all sufficiently large arguments.
The notation is abused to the extent that one conventionally writes, for example, 𝑓(𝑛) = 𝑂 𝑛2 rather than the more
correct 𝑓 = 𝑂 𝑠𝑞𝑢𝑎𝑟𝑒 . Similarly, one writes 𝑓(𝑛) = 𝑂 𝑛 rather than 𝑓 = 𝑂 𝑖𝑑 .
…
What 𝑂-notation brings out is an upper bound on the asymptotic growth of functions. For this reason, estimating
the performance of a program using 𝑂-notation is called asymptotic upper-bound analysis.
Richard Bird
49. For example, the time complexity of reverse′ is 𝑂(𝑛). However, saying that reverse takes 𝑂(𝑛2) steps on a list of
length 𝑛 does not mean that it does not take, say, 𝑂(𝑛) steps. For more precision we need additional notation.
We say that 𝑓 is order at least 𝑔, and write 𝑓 = 𝛺 𝑔 if there exists a positive constant C and natural number n0 such
that 𝑓(𝑛) ≥ C 𝑔(𝑛) for all 𝑛 ≥ n0.
Putting the two kinds of bound together, we say 𝑓 is order exactly 𝑔, and write 𝑓 = 𝛩(𝑔) if 𝑓 = 𝑂(𝑔) and 𝑓 = 𝛺 𝑔 .
In other words, 𝑓 = 𝛩(𝑔) if there are two positive constants C 1 and C2 such that
C1 𝑔 𝑛 ≤ 𝑓 𝑛 ≤ 𝐶2 𝑔(𝑛)
for all sufficiently large 𝑛. Then we can assert that the time of reverse is 𝛩(𝑛2) and the time of reverse′ is 𝛩(𝑛).
7.2.2 Timing analysis
Given a function 𝑓 we will write T 𝑓 𝑛 to denote an asymptotic estimate of the number of reduction steps
required to evaluate 𝑓 on an argument of ‘size’ 𝑛 in the worst case. Moreover, for reasons explained in a moment, we
will assume eager, not lazy, evaluation as a reduction strategy. In particular, we can write
T 𝑟𝑒𝑣𝑒𝑟𝑠𝑒 𝑛 = Θ 𝑛2
T reverse′ 𝑛 = Θ 𝑛
The definition of T requires some amplification. Firstly, T 𝑓 does not refer to the time complexity of a function 𝑓
but to the complexity of a given definition of 𝑓. Time complexity is a property of an expression, not of the value of the
expression.
Richard Bird
50. Secondly, we do not formalize the notion of size, since different measures are appropriate in different situations. For
example, the cost of evaluating 𝑥𝑠 ⧺ 𝑦𝑠 is best measured in terms of 𝑚 and 𝑛, where 𝑚 = 𝑙𝑒𝑛𝑔𝑡ℎ(𝑥𝑠) and 𝑛 =
𝑙𝑒𝑛𝑔𝑡ℎ(𝑦𝑠). In fact, we have
𝑇 ⧺ (𝑚, 𝑛) = Θ(𝑚)
The proof is left as an exercise. Next, consider 𝑐𝑜𝑛𝑐𝑎𝑡 𝑥𝑠𝑠. Here the measure of 𝑥𝑠𝑠 is more difficult. In the simple
case that 𝑥𝑠𝑠 is a list of length 𝑚, consisting of lists of length 𝑛, we have
𝑇 𝑐𝑜𝑛𝑐𝑎𝑡 𝑚, 𝑛 = Θ(𝑚𝑛)
We will prove this result below. The estimate for 𝑇 𝑐𝑜𝑛𝑐𝑎𝑡 therefore refers only to lists of lists with a common
length; though limited, such restrictions make timing analyses more tractable.
The third remark is to emphasise that T 𝑓 𝑛 is an estimate of worst-case running time only. This will be sufficient
for our purposes, although best-case and average-case analyses are also important in practice.
The fourth and crucial remark is that T 𝑓 𝑛 is determined under an eager evaluation model of reduction. The
reason is simply that estimating the number of reduction steps under lazy evaluation is difficult, and is still the subject
of ongoing research.
…
Timing analysis under eager reduction is simpler because it is compositional. Since lazy evaluation never requires
more reduction steps than eager evaluation, any upper bound for T 𝑓 𝑛 will also be an upper bound under lazy
evaluation. Furthermore, in many cases of interest, a lower bound for T 𝑓 𝑛 will also be a lower bound under lazy
evaluation.
Richard Bird
51. Images Source: Introduction to Algorithms (3rd edition)
by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein | Page 45 | Figure 3.1
𝑓 𝑛 = 𝛩 𝑔 𝑛
C1 𝑔 𝑛 ≤ 𝑓 𝑛 ≤ 𝐶2 𝑔(𝑛)
for all sufficiently large 𝑛
𝑓 𝑛 = 𝑂 𝑔 𝑛
𝑓 𝑛 ≤ C 𝑔(𝑛)
for all 𝑛 ≥ n0
𝑓(𝑛) = 𝛺(𝑔(𝑛))
𝑓(𝑛) ≥ C 𝑔(𝑛)
for all 𝑛 ≥ n0
52. reverse ∷ α → [α]
reverse = 𝑓𝑜𝑙𝑑𝑟 𝑠𝑛𝑜𝑐
𝒘𝒉𝒆𝒓𝒆 𝑠𝑛𝑜𝑐 𝑥 𝑥𝑠 = append 𝑥𝑠 [𝑥]
reverse′ ∷ α → [α]
reverse′ = 𝑓𝑜𝑙𝑑𝑙 𝑠𝑐𝑜𝑛
𝒘𝒉𝒆𝒓𝒆 𝑠𝑐𝑜𝑛 𝑥𝑠 𝑥 = 𝑥 : 𝑥𝑠
T 𝑟𝑒𝑣𝑒𝑟𝑠𝑒 𝑛 = Θ 𝑛2
T reverse′ 𝑛 = Θ 𝑛
concat′ ∷ [ α ] → [α]
concat′ = 𝑓𝑜𝑙𝑑𝑙 append [ ]
𝑇 concat 𝑚, 𝑛 = Θ(𝑚𝑛)
𝑇 concat′ 𝑚, 𝑛 = Θ(𝑚2 𝑛)
append ∷ [α] → [α] → [α]
append 𝑥𝑠 𝑦𝑠 = 𝑓𝑜𝑙𝑑𝑟 ∶ 𝑦𝑠 xs
append′ ∷ [α] → [α] → [α]
append′ 𝑥𝑠 𝑦𝑠 = 𝑓𝑜𝑙𝑑𝑙 𝑠𝑐𝑜𝑛 𝑦𝑠 (reverse′ xs)
𝒘𝒉𝒆𝒓𝒆 𝑠𝑐𝑜𝑛 𝑥𝑠 𝑥 = 𝑥 : 𝑥𝑠
𝑇 append 𝑚, 𝑛 = Θ(𝑚)
𝑇 append′ 𝑚, 𝑛 = Θ(𝑚)
Following that introduction to (refresher of) asymptotic analysis, this slide is a
quick reminder, using 𝛩 –notation, that whether it is more efficient to
implement a function using 𝑓𝑜𝑙𝑑𝑟, or using 𝑓𝑜𝑙𝑑𝑙, depends on the function.
concat ∷ [ α ] → [α]
concat = 𝑓𝑜𝑙𝑑𝑟 append [ ]
I have renamed cons to scon, because I
regard ∶ as cons, and because the order of
its arguments is the opposite of that of ∶ ,
and I find that the name scon conveys the
fact that there is this inversion happening.
To be consistent with Tony Morris, we are
defining append functions rather than an
infix append operator ⧺.
I have added xs to the definition of append.
append′ is Θ(𝑚) because in this case 𝑓𝑜𝑙𝑑𝑙 is
Θ(𝑚), and reverse′ is Θ 𝑚 .
53. That’s all for Part 3. I hope you found it useful.
We’ll continue looking at Tony’s presentation in Part 4.
See you there.