SlideShare a Scribd company logo
1 of 8
Download to read offline
CHEAT-SHEET
Folding
#4
∢
/ 
π’‚πŸŽ ∢
/ 
π’‚πŸ ∢
/ 
π’‚πŸ ∢
/ 
π’‚πŸ‘
𝒇
/ 
π’‚πŸŽ 𝒇
/ 
π’‚πŸ 𝒇
/ 
π’‚πŸ 𝒇
/ 
π’‚πŸ‘ 𝒆
@philip_schwarz
slides by https://fpilluminated.com/
We want to write function π’…π’†π’„π’Šπ’Žπ’‚π’, which given the digits of an integer number
[𝑑0, 𝑑1, … , 𝑑𝑛]
computes the integer value of the number
-
&'(
)
π‘‘π‘˜ βˆ— 10)*&
Thanks to the universal property of fold, if we are able to define π’…π’†π’„π’Šπ’Žπ’‚π’ so that its equations match those on the left hand side of the
following equivalence, then we are also able to implement π’…π’†π’„π’Šπ’Žπ’‚π’ using a right fold
i.e. given π‘“π‘œπ‘™π‘‘π‘Ÿ
π‘“π‘œπ‘™π‘‘π‘Ÿ :: 𝛼 β†’ 𝛽 β†’ 𝛽 β†’ 𝛽 β†’ 𝛼 β†’ 𝛽
π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 = 𝑣
π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 π‘₯ ∢ π‘₯𝑠 = 𝑓 π‘₯ π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 π‘₯𝑠
we can reimplement π’…π’†π’„π’Šπ’Žπ’‚π’ like this:
π’…π’†π’„π’Šπ’Žπ’‚π’ = π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣
The universal property of 𝒇𝒐𝒍𝒅
π’ˆ = 𝒗 ⟺ π’ˆ = 𝒇𝒐𝒍𝒅 𝒇 𝒗 π’ˆ :: 𝛼 β†’ 𝛽
π’ˆ π‘₯ ∢ π‘₯𝑠 = 𝒇 π‘₯ π’ˆ π‘₯𝑠 𝒗 :: 𝛽
𝒇 :: 𝛼 β†’ 𝛽 β†’ 𝛽
scala> decimal(List(1,2,3,4))
val res0: Int = 1234
haskell> decimal [1,2,3,4]
1234
𝑑0 βˆ— 103 + 𝑑1 βˆ— 102 + 𝑑2 βˆ— 101 + 𝑑3 βˆ— 100 = 1 βˆ— 1000 + 2 βˆ— 100 + 3 βˆ— 10 + 4 βˆ— 1 = 1234
Notice that 𝒇 has two parameters: the head of the list, and the result of recursively calling π’ˆ with the tail of the list
π’ˆ π‘₯ ∢ π‘₯𝑠 = 𝒇 π‘₯ π’ˆ π‘₯𝑠
In order to define our π’…π’†π’„π’Šπ’Žπ’‚π’ function however, the two parameters of 𝒇 are not sufficient. When π’…π’†π’„π’Šπ’Žπ’‚π’ is passed [π‘‘π‘˜, … , 𝑑𝑛], 𝒇 is
passed digit π‘‘π‘˜, so 𝒇 needs 𝑛 and π‘˜ in order to compute 10)*&
, but 𝑛 βˆ’ π‘˜ is the number of elements in [π‘‘π‘˜, … , 𝑑𝑛] minus one, so by nesting
the definition of 𝒇 inside that of π’…π’†π’„π’Šπ’Žπ’‚π’, we can avoid explicitly adding a third parameter to 𝒇 :
We nested 𝒇 inside π’…π’†π’„π’Šπ’Žπ’‚π’, so that the equations of π’…π’†π’„π’Šπ’Žπ’‚π’ match (almost) those of π’ˆ. They don’t match perfectly, in that the 𝒇 nested
inside π’…π’†π’„π’Šπ’Žπ’‚π’ depends on π’…π’†π’„π’Šπ’Žπ’‚π’β€™s list parameter, whereas the 𝒇 nested inside π’ˆ does not depend on π’ˆβ€™s list parameter. Are we still able
to redefine π’…π’†π’„π’Šπ’Žπ’‚π’ using π‘“π‘œπ‘™π‘‘π‘Ÿ? If the match had been perfect, we would be able to define π’…π’†π’„π’Šπ’Žπ’‚π’ = π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 0 (with 𝒗 = 0), but
because 𝒇 needs to know the value of 𝑛 βˆ’ π‘˜, we can’t just pass 𝒇 to π‘“π‘œπ‘™π‘‘π‘Ÿ, and use 0 as the initial accumulator. Instead, we need to use (0, 0)
as the accumulator (the second 0 being the initial value of 𝑛 βˆ’ π‘˜, when π‘˜ = 𝑛), and pass to π‘“π‘œπ‘™π‘‘π‘Ÿ a helper function β„Ž that manages 𝑛 βˆ’ π‘˜
and that wraps 𝒇, so that the latter has access to 𝑛 βˆ’ π‘˜.
def h(d: Int, acc: (Int,Int)): (Int,Int) = acc match { case (ds, e) =>
def f(d: Int, ds: Int): Int =
d * Math.pow(10, e).toInt + ds
(f(d, ds), e + 1)
}
def decimal(ds: List[Int]): Int =
ds.foldRight((0,0))(h).head
h :: Int -> (Int,Int) -> (Int,Int)
h d (ds, e) = (f d ds, e + 1) where
f :: Int -> Int -> Int
f d ds = d * (10 ^ e) + ds
decimal :: [Int] -> Int
decimal ds = fst (foldr h (0,0) ds)
def decimal(digits: List[Int]): Int =
val e = digits.length-1
def f(d: Int, ds: Int): Int =
d * Math.pow(10, e).toInt + ds
digits match
case Nil => 0
case d +: ds => f(d, decimal(ds))
decimal :: [Int] -> Int
decimal [] = 0
decimal (d:ds) = f d (decimal ds) where
e = length ds
f :: Int -> Int -> Int
f d ds = d * (10 ^ e) + ds
The unnecessary complexity
of the π’…π’†π’„π’Šπ’Žπ’‚π’ functions
on this slide is purely due to
them being defined in terms
of 𝒇 . See next slide for
simpler refactored versions
in which 𝒇 is inlined.
def f(d: Int, acc: (Int,Int)): (Int,Int) = acc match
case (ds, e) => (d * Math.pow(10, e).toInt + ds, e + 1)
def decimal(ds: List[Int]): Int =
ds.foldRight((0,0))(f).head
f :: Int -> (Int,Int) -> (Int,Int)
f d (ds, e) = (d * (10 ^ e) + ds, e + 1)
decimal :: [Int] -> Int
decimal ds = fst (foldr f (0,0) ds)
def decimal(digits: List[Int]): Int = digits match
case Nil => 0
case d +: ds => d * Math.pow(10, ds.length).toInt + decimal(ds)
decimal :: [Int] -> Int
decimal [] = 0
decimal (d:ds) = d*(10^(length ds))+(decimal ds)
Same π’…π’†π’„π’Šπ’Žπ’‚π’ functions as on the previous slide, but refactored as follows:
1. inlined 𝒇 in all four functions
2. inlined e in the first two functions
3. renamed 𝒉 to 𝒇 in the last two functions
Not every function on lists can be defined as an instance of π‘“π‘œπ‘™π‘‘π‘Ÿ. For example, zip cannot be so defined. Even for those that
can, an alternative definition may be more efficient. To illustrate, suppose we want a function decimal that takes a list of digits
and returns the corresponding decimal number; thus
π‘‘π‘’π‘π‘–π‘šπ‘Žπ‘™ [π‘₯0, π‘₯1, … , π‘₯n] = βˆ‘!"#
$
π‘₯π‘˜10($&!)
It is assumed that the most significant digit comes first in the list. One way to compute decimal efficiently is by a process of
multiplying each digit by ten and adding in the following digit. For example
π‘‘π‘’π‘π‘–π‘šπ‘Žπ‘™ π‘₯0, π‘₯1, π‘₯2 = 10 Γ— 10 Γ— 10 Γ— 0 + π‘₯0 + π‘₯1 + π‘₯2
This decomposition of a sum of powers is known as Horner’s rule.
Suppose we define βŠ• by 𝑛 βŠ• π‘₯ = 10 Γ— 𝑛 + π‘₯. Then we can rephrase the above equation as
π‘‘π‘’π‘π‘–π‘šπ‘Žπ‘™ π‘₯0, π‘₯1, π‘₯2 = (0 βŠ• π‘₯0) βŠ• π‘₯1 βŠ• π‘₯2
This is almost like an instance of π‘“π‘œπ‘™π‘‘π‘Ÿ, except that the grouping is the other way round, and the starting value appears on the
left, not on the right. In fact the computation is dual: instead of processing from right to left, the computation processes from
left to right.
This example motivates the introduction of a second fold operator called π‘“π‘œπ‘™π‘‘π‘™ (pronounced β€˜fold left’). Informally:
π‘“π‘œπ‘™π‘‘π‘™ βŠ• 𝑒 π‘₯0, π‘₯1, … , π‘₯𝑛 βˆ’ 1 = … ((𝑒 βŠ• π‘₯0) βŠ• π‘₯1) … βŠ• π‘₯𝑛 βˆ’ 1
The parentheses group from the left, which is the reason for the name. The full definition of π‘“π‘œπ‘™π‘‘π‘™ is
π‘“π‘œπ‘™π‘‘π‘™ ∷ 𝛽 β†’ 𝛼 β†’ 𝛽 β†’ 𝛽 β†’ 𝛼 β†’ 𝛽
π‘“π‘œπ‘™π‘‘π‘™ 𝑓 𝑒 = 𝑒
π‘“π‘œπ‘™π‘‘π‘™ 𝑓 𝑒 π‘₯: π‘₯𝑠 = π‘“π‘œπ‘™π‘‘π‘™ 𝑓 𝑓 𝑒 π‘₯ π‘₯𝑠
Richard Bird
The definition of π’…π’†π’„π’Šπ’Žπ’‚π’ using a right fold is inefficient because it computes βˆ‘!"#
$
π‘‘π‘˜ βˆ— 10$&!
by computing 10$&!
for each π‘˜.
If we look back at our initial recursive definition of π’…π’†π’„π’Šπ’Žπ’‚π’, we see that it splits its list parameter into a head and a tail.
If we get π’…π’†π’„π’Šπ’Žπ’‚π’ to split the list into init and last, we can make it more efficient by using Horner’s rule:
We can then improve on that by going back to splitting the list into a head and a tail, and making π’…π’†π’„π’Šπ’Žπ’‚π’ tail recursive:
And finally, we can improve on that by defining π’…π’†π’„π’Šπ’Žπ’‚π’ using a left fold:
(βŠ•) :: Int -> Int -> Int
n βŠ• d = 10 * n + d
decimal :: [Int] -> Int
decimal [] = 0
decimal (d:ds) = d*(10^(length ds)) + (decimal ds)
def decimal(digits: List[Int]): Int = digits match
case Nil => 0
case d +: ds => d * Math.pow(10, ds.length).toInt + decimal(ds)
extension (n: Int)
def βŠ•(d Int): Int = 10 * n + d
decimal :: [Int] -> Int -> Int
decimal [] acc = acc
decimal (d:ds) acc = decimal ds (acc βŠ•d)
def decimal(ds: List[Int], acc: Int=0): Int = digits match
case Nil => acc
case d +: ds => decimal(ds, acc βŠ• d)
decimal :: [Int] -> Int
decimal = foldl (βŠ•) 0
decimal :: [Int] -> Int
decimal [] = 0
decimal ds = (decimal (init ds)) βŠ• (last ds)
def decimal(digits: List[Int]): Int = digits match
case Nil => 0
case ds :+ d => decimal(ds) βŠ• d
def decimal(ds: List[Int]): Int =
ds.foldLeft(0)(_βŠ•_)
Recap
In the case of the π’…π’†π’„π’Šπ’Žπ’‚π’ function, defining it using a left fold is simple and mathematically more efficient
whereas defining it using a right fold is more complex and mathematically less efficient
def decimal(ds: List[Int]): Int =
ds.foldRight((0,0))(f).head
def f(d: Int, acc: (Int,Int)): (Int,Int) = acc match
case (ds, e) => (d * Math.pow(10, e).toInt + ds, e + 1)
decimal :: [Int] -> Int
decimal ds = fst (foldr f (0,0) ds)
f :: Int -> (Int,Int) -> (Int,Int)
f d (ds, e) = (d * (10 ^ e) + ds, e + 1)
decimal :: [Int] -> Int
decimal = foldl (βŠ•) 0
(βŠ•) :: Int -> Int -> Int
n βŠ• d = 10 * n + d
def decimal(ds: List[Int]): Int =
ds.foldLeft(0)(_βŠ•_)
extension (n: Int)
def βŠ•(d Int): Int = 10 * n + d
π’…π’†π’„π’Šπ’Žπ’‚π’ 1,2,3,4 = 𝑑0 βˆ— 103 + (𝑑1 βˆ— 102 + (𝑑2 βˆ— 101 + (𝑑3 βˆ— 100 + 0))) = 1 βˆ— 1000 + (2 βˆ— 100 + (3 βˆ— 10 + (4 βˆ— 1 + 0))) = 1234
π’…π’†π’„π’Šπ’Žπ’‚π’ 1,2,3,4 = 10 βˆ— 10 βˆ— 10 βˆ— 10 βˆ— 0 + 𝑑0 + 𝑑1 + 𝑑2 + 𝑑3 = 10 βˆ— (10 βˆ— 10 βˆ— 10 βˆ— 0 + 1 + 2 + 3) + 4 = 1234
https://fpilluminated.com/
inspired
by

More Related Content

Similar to Folding Cheat Sheet #4 - fourth in a series

Teeing Up Python - Code Golf
Teeing Up Python - Code GolfTeeing Up Python - Code Golf
Teeing Up Python - Code GolfYelp Engineering
Β 
Lecture 01 reals number system
Lecture 01 reals number systemLecture 01 reals number system
Lecture 01 reals number systemHazel Joy Chong
Β 
Python 04-ifelse-return-input-strings.pptx
Python 04-ifelse-return-input-strings.pptxPython 04-ifelse-return-input-strings.pptx
Python 04-ifelse-return-input-strings.pptxTseChris
Β 
Complex function
Complex functionComplex function
Complex functionShrey Patel
Β 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftAleksandras Smirnovas
Β 
23UCACC11 Python Programming (MTNC) (BCA)
23UCACC11 Python Programming (MTNC) (BCA)23UCACC11 Python Programming (MTNC) (BCA)
23UCACC11 Python Programming (MTNC) (BCA)ssuser7f90ae
Β 
Lists.pptx
Lists.pptxLists.pptx
Lists.pptxYagna15
Β 
Scala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsScala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsKirill Kozlov
Β 
Python Lecture 11
Python Lecture 11Python Lecture 11
Python Lecture 11Inzamam Baig
Β 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc DuponcheelStephan Janssen
Β 
iRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat SheetiRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat SheetSamuel Lampa
Β 
Understanding the "Chain Rule" for Derivatives by Deriving Your Own Version
Understanding the "Chain Rule" for Derivatives by Deriving Your Own VersionUnderstanding the "Chain Rule" for Derivatives by Deriving Your Own Version
Understanding the "Chain Rule" for Derivatives by Deriving Your Own VersionJames Smith
Β 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaDaniel Cukier
Β 
functions
 functions  functions
functions Gaditek
Β 

Similar to Folding Cheat Sheet #4 - fourth in a series (20)

Array
ArrayArray
Array
Β 
Teeing Up Python - Code Golf
Teeing Up Python - Code GolfTeeing Up Python - Code Golf
Teeing Up Python - Code Golf
Β 
Lecture 01 reals number system
Lecture 01 reals number systemLecture 01 reals number system
Lecture 01 reals number system
Β 
Python 04-ifelse-return-input-strings.pptx
Python 04-ifelse-return-input-strings.pptxPython 04-ifelse-return-input-strings.pptx
Python 04-ifelse-return-input-strings.pptx
Β 
Frp2016 3
Frp2016 3Frp2016 3
Frp2016 3
Β 
Complex function
Complex functionComplex function
Complex function
Β 
Maths number system
Maths   number systemMaths   number system
Maths number system
Β 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
Β 
23UCACC11 Python Programming (MTNC) (BCA)
23UCACC11 Python Programming (MTNC) (BCA)23UCACC11 Python Programming (MTNC) (BCA)
23UCACC11 Python Programming (MTNC) (BCA)
Β 
Lists.pptx
Lists.pptxLists.pptx
Lists.pptx
Β 
Scala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsScala. Introduction to FP. Monads
Scala. Introduction to FP. Monads
Β 
Python Lecture 11
Python Lecture 11Python Lecture 11
Python Lecture 11
Β 
Monad Fact #4
Monad Fact #4Monad Fact #4
Monad Fact #4
Β 
Ch8b
Ch8bCh8b
Ch8b
Β 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
Β 
7. basics
7. basics7. basics
7. basics
Β 
iRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat SheetiRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat Sheet
Β 
Understanding the "Chain Rule" for Derivatives by Deriving Your Own Version
Understanding the "Chain Rule" for Derivatives by Deriving Your Own VersionUnderstanding the "Chain Rule" for Derivatives by Deriving Your Own Version
Understanding the "Chain Rule" for Derivatives by Deriving Your Own Version
Β 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
Β 
functions
 functions  functions
functions
Β 

More from Philip Schwarz

Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
Β 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
Β 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
Β 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three ApproachesPhilip Schwarz
Β 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
Β 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsPhilip Schwarz
Β 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaPhilip Schwarz
Β 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
Β 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
Β 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsPhilip Schwarz
Β 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
Β 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...Philip Schwarz
Β 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, 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
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
Β 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
Β 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
Β 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...Philip Schwarz
Β 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsPhilip Schwarz
Β 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Philip Schwarz
Β 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Philip Schwarz
Β 

More from Philip Schwarz (20)

Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
Β 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
Β 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
Β 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
Β 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
Β 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
Β 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
Β 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
Β 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
Β 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
Β 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Β 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
Β 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Β 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Β 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
Β 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Β 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Β 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axioms
Β 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Β 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Β 

Recently uploaded

Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfWilly Marroquin (WillyDevNET)
Β 
call girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈ
call girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈcall girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈ
call girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈDelhi Call girls
Β 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
Β 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
Β 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
Β 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
Β 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
Β 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
Β 
Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...Steffen Staab
Β 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
Β 
CHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICE9953056974 Low Rate Call Girls In Saket, Delhi NCR
Β 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
Β 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
Β 
(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...
(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...
(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...gurkirankumar98700
Β 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
Β 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
Β 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
Β 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
Β 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
Β 

Recently uploaded (20)

Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
Β 
call girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈ
call girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈcall girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈ
call girls in Vaishali (Ghaziabad) πŸ” >ΰΌ’8448380779 πŸ” genuine Escort Service πŸ”βœ”οΈβœ”οΈ
Β 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
Β 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Β 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
Β 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
Β 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
Β 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
Β 
Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data SpacesΒ - and Epistemic Querying of RDF-...
Β 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
Β 
Vip Call Girls Noida ➑️ Delhi ➑️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➑️ Delhi ➑️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➑️ Delhi ➑️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➑️ Delhi ➑️ 9999965857 No Advance 24HRS Live
Β 
CHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )πŸ” 9953056974πŸ”(=)/CALL GIRLS SERVICE
Β 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
Β 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Β 
(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...
(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...
(Genuine) Escort Service Lucknow | Starting β‚Ή,5K To @25k with A/C πŸ§‘πŸ½β€β€οΈβ€πŸ§‘πŸ» 89...
Β 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Β 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
Β 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
Β 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
Β 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
Β 

Folding Cheat Sheet #4 - fourth in a series

  • 1. CHEAT-SHEET Folding #4 ∢ / π’‚πŸŽ ∢ / π’‚πŸ ∢ / π’‚πŸ ∢ / π’‚πŸ‘ 𝒇 / π’‚πŸŽ 𝒇 / π’‚πŸ 𝒇 / π’‚πŸ 𝒇 / π’‚πŸ‘ 𝒆 @philip_schwarz slides by https://fpilluminated.com/
  • 2. We want to write function π’…π’†π’„π’Šπ’Žπ’‚π’, which given the digits of an integer number [𝑑0, 𝑑1, … , 𝑑𝑛] computes the integer value of the number - &'( ) π‘‘π‘˜ βˆ— 10)*& Thanks to the universal property of fold, if we are able to define π’…π’†π’„π’Šπ’Žπ’‚π’ so that its equations match those on the left hand side of the following equivalence, then we are also able to implement π’…π’†π’„π’Šπ’Žπ’‚π’ using a right fold i.e. given π‘“π‘œπ‘™π‘‘π‘Ÿ π‘“π‘œπ‘™π‘‘π‘Ÿ :: 𝛼 β†’ 𝛽 β†’ 𝛽 β†’ 𝛽 β†’ 𝛼 β†’ 𝛽 π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 = 𝑣 π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 π‘₯ ∢ π‘₯𝑠 = 𝑓 π‘₯ π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 π‘₯𝑠 we can reimplement π’…π’†π’„π’Šπ’Žπ’‚π’ like this: π’…π’†π’„π’Šπ’Žπ’‚π’ = π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 𝑣 The universal property of 𝒇𝒐𝒍𝒅 π’ˆ = 𝒗 ⟺ π’ˆ = 𝒇𝒐𝒍𝒅 𝒇 𝒗 π’ˆ :: 𝛼 β†’ 𝛽 π’ˆ π‘₯ ∢ π‘₯𝑠 = 𝒇 π‘₯ π’ˆ π‘₯𝑠 𝒗 :: 𝛽 𝒇 :: 𝛼 β†’ 𝛽 β†’ 𝛽 scala> decimal(List(1,2,3,4)) val res0: Int = 1234 haskell> decimal [1,2,3,4] 1234 𝑑0 βˆ— 103 + 𝑑1 βˆ— 102 + 𝑑2 βˆ— 101 + 𝑑3 βˆ— 100 = 1 βˆ— 1000 + 2 βˆ— 100 + 3 βˆ— 10 + 4 βˆ— 1 = 1234
  • 3. Notice that 𝒇 has two parameters: the head of the list, and the result of recursively calling π’ˆ with the tail of the list π’ˆ π‘₯ ∢ π‘₯𝑠 = 𝒇 π‘₯ π’ˆ π‘₯𝑠 In order to define our π’…π’†π’„π’Šπ’Žπ’‚π’ function however, the two parameters of 𝒇 are not sufficient. When π’…π’†π’„π’Šπ’Žπ’‚π’ is passed [π‘‘π‘˜, … , 𝑑𝑛], 𝒇 is passed digit π‘‘π‘˜, so 𝒇 needs 𝑛 and π‘˜ in order to compute 10)*& , but 𝑛 βˆ’ π‘˜ is the number of elements in [π‘‘π‘˜, … , 𝑑𝑛] minus one, so by nesting the definition of 𝒇 inside that of π’…π’†π’„π’Šπ’Žπ’‚π’, we can avoid explicitly adding a third parameter to 𝒇 : We nested 𝒇 inside π’…π’†π’„π’Šπ’Žπ’‚π’, so that the equations of π’…π’†π’„π’Šπ’Žπ’‚π’ match (almost) those of π’ˆ. They don’t match perfectly, in that the 𝒇 nested inside π’…π’†π’„π’Šπ’Žπ’‚π’ depends on π’…π’†π’„π’Šπ’Žπ’‚π’β€™s list parameter, whereas the 𝒇 nested inside π’ˆ does not depend on π’ˆβ€™s list parameter. Are we still able to redefine π’…π’†π’„π’Šπ’Žπ’‚π’ using π‘“π‘œπ‘™π‘‘π‘Ÿ? If the match had been perfect, we would be able to define π’…π’†π’„π’Šπ’Žπ’‚π’ = π‘“π‘œπ‘™π‘‘π‘Ÿ 𝑓 0 (with 𝒗 = 0), but because 𝒇 needs to know the value of 𝑛 βˆ’ π‘˜, we can’t just pass 𝒇 to π‘“π‘œπ‘™π‘‘π‘Ÿ, and use 0 as the initial accumulator. Instead, we need to use (0, 0) as the accumulator (the second 0 being the initial value of 𝑛 βˆ’ π‘˜, when π‘˜ = 𝑛), and pass to π‘“π‘œπ‘™π‘‘π‘Ÿ a helper function β„Ž that manages 𝑛 βˆ’ π‘˜ and that wraps 𝒇, so that the latter has access to 𝑛 βˆ’ π‘˜. def h(d: Int, acc: (Int,Int)): (Int,Int) = acc match { case (ds, e) => def f(d: Int, ds: Int): Int = d * Math.pow(10, e).toInt + ds (f(d, ds), e + 1) } def decimal(ds: List[Int]): Int = ds.foldRight((0,0))(h).head h :: Int -> (Int,Int) -> (Int,Int) h d (ds, e) = (f d ds, e + 1) where f :: Int -> Int -> Int f d ds = d * (10 ^ e) + ds decimal :: [Int] -> Int decimal ds = fst (foldr h (0,0) ds) def decimal(digits: List[Int]): Int = val e = digits.length-1 def f(d: Int, ds: Int): Int = d * Math.pow(10, e).toInt + ds digits match case Nil => 0 case d +: ds => f(d, decimal(ds)) decimal :: [Int] -> Int decimal [] = 0 decimal (d:ds) = f d (decimal ds) where e = length ds f :: Int -> Int -> Int f d ds = d * (10 ^ e) + ds The unnecessary complexity of the π’…π’†π’„π’Šπ’Žπ’‚π’ functions on this slide is purely due to them being defined in terms of 𝒇 . See next slide for simpler refactored versions in which 𝒇 is inlined.
  • 4. def f(d: Int, acc: (Int,Int)): (Int,Int) = acc match case (ds, e) => (d * Math.pow(10, e).toInt + ds, e + 1) def decimal(ds: List[Int]): Int = ds.foldRight((0,0))(f).head f :: Int -> (Int,Int) -> (Int,Int) f d (ds, e) = (d * (10 ^ e) + ds, e + 1) decimal :: [Int] -> Int decimal ds = fst (foldr f (0,0) ds) def decimal(digits: List[Int]): Int = digits match case Nil => 0 case d +: ds => d * Math.pow(10, ds.length).toInt + decimal(ds) decimal :: [Int] -> Int decimal [] = 0 decimal (d:ds) = d*(10^(length ds))+(decimal ds) Same π’…π’†π’„π’Šπ’Žπ’‚π’ functions as on the previous slide, but refactored as follows: 1. inlined 𝒇 in all four functions 2. inlined e in the first two functions 3. renamed 𝒉 to 𝒇 in the last two functions
  • 5. Not every function on lists can be defined as an instance of π‘“π‘œπ‘™π‘‘π‘Ÿ. For example, zip cannot be so defined. Even for those that can, an alternative definition may be more efficient. To illustrate, suppose we want a function decimal that takes a list of digits and returns the corresponding decimal number; thus π‘‘π‘’π‘π‘–π‘šπ‘Žπ‘™ [π‘₯0, π‘₯1, … , π‘₯n] = βˆ‘!"# $ π‘₯π‘˜10($&!) It is assumed that the most significant digit comes first in the list. One way to compute decimal efficiently is by a process of multiplying each digit by ten and adding in the following digit. For example π‘‘π‘’π‘π‘–π‘šπ‘Žπ‘™ π‘₯0, π‘₯1, π‘₯2 = 10 Γ— 10 Γ— 10 Γ— 0 + π‘₯0 + π‘₯1 + π‘₯2 This decomposition of a sum of powers is known as Horner’s rule. Suppose we define βŠ• by 𝑛 βŠ• π‘₯ = 10 Γ— 𝑛 + π‘₯. Then we can rephrase the above equation as π‘‘π‘’π‘π‘–π‘šπ‘Žπ‘™ π‘₯0, π‘₯1, π‘₯2 = (0 βŠ• π‘₯0) βŠ• π‘₯1 βŠ• π‘₯2 This is almost like an instance of π‘“π‘œπ‘™π‘‘π‘Ÿ, except that the grouping is the other way round, and the starting value appears on the left, not on the right. In fact the computation is dual: instead of processing from right to left, the computation processes from left to right. This example motivates the introduction of a second fold operator called π‘“π‘œπ‘™π‘‘π‘™ (pronounced β€˜fold left’). Informally: π‘“π‘œπ‘™π‘‘π‘™ βŠ• 𝑒 π‘₯0, π‘₯1, … , π‘₯𝑛 βˆ’ 1 = … ((𝑒 βŠ• π‘₯0) βŠ• π‘₯1) … βŠ• π‘₯𝑛 βˆ’ 1 The parentheses group from the left, which is the reason for the name. The full definition of π‘“π‘œπ‘™π‘‘π‘™ is π‘“π‘œπ‘™π‘‘π‘™ ∷ 𝛽 β†’ 𝛼 β†’ 𝛽 β†’ 𝛽 β†’ 𝛼 β†’ 𝛽 π‘“π‘œπ‘™π‘‘π‘™ 𝑓 𝑒 = 𝑒 π‘“π‘œπ‘™π‘‘π‘™ 𝑓 𝑒 π‘₯: π‘₯𝑠 = π‘“π‘œπ‘™π‘‘π‘™ 𝑓 𝑓 𝑒 π‘₯ π‘₯𝑠 Richard Bird The definition of π’…π’†π’„π’Šπ’Žπ’‚π’ using a right fold is inefficient because it computes βˆ‘!"# $ π‘‘π‘˜ βˆ— 10$&! by computing 10$&! for each π‘˜.
  • 6. If we look back at our initial recursive definition of π’…π’†π’„π’Šπ’Žπ’‚π’, we see that it splits its list parameter into a head and a tail. If we get π’…π’†π’„π’Šπ’Žπ’‚π’ to split the list into init and last, we can make it more efficient by using Horner’s rule: We can then improve on that by going back to splitting the list into a head and a tail, and making π’…π’†π’„π’Šπ’Žπ’‚π’ tail recursive: And finally, we can improve on that by defining π’…π’†π’„π’Šπ’Žπ’‚π’ using a left fold: (βŠ•) :: Int -> Int -> Int n βŠ• d = 10 * n + d decimal :: [Int] -> Int decimal [] = 0 decimal (d:ds) = d*(10^(length ds)) + (decimal ds) def decimal(digits: List[Int]): Int = digits match case Nil => 0 case d +: ds => d * Math.pow(10, ds.length).toInt + decimal(ds) extension (n: Int) def βŠ•(d Int): Int = 10 * n + d decimal :: [Int] -> Int -> Int decimal [] acc = acc decimal (d:ds) acc = decimal ds (acc βŠ•d) def decimal(ds: List[Int], acc: Int=0): Int = digits match case Nil => acc case d +: ds => decimal(ds, acc βŠ• d) decimal :: [Int] -> Int decimal = foldl (βŠ•) 0 decimal :: [Int] -> Int decimal [] = 0 decimal ds = (decimal (init ds)) βŠ• (last ds) def decimal(digits: List[Int]): Int = digits match case Nil => 0 case ds :+ d => decimal(ds) βŠ• d def decimal(ds: List[Int]): Int = ds.foldLeft(0)(_βŠ•_)
  • 7. Recap In the case of the π’…π’†π’„π’Šπ’Žπ’‚π’ function, defining it using a left fold is simple and mathematically more efficient whereas defining it using a right fold is more complex and mathematically less efficient def decimal(ds: List[Int]): Int = ds.foldRight((0,0))(f).head def f(d: Int, acc: (Int,Int)): (Int,Int) = acc match case (ds, e) => (d * Math.pow(10, e).toInt + ds, e + 1) decimal :: [Int] -> Int decimal ds = fst (foldr f (0,0) ds) f :: Int -> (Int,Int) -> (Int,Int) f d (ds, e) = (d * (10 ^ e) + ds, e + 1) decimal :: [Int] -> Int decimal = foldl (βŠ•) 0 (βŠ•) :: Int -> Int -> Int n βŠ• d = 10 * n + d def decimal(ds: List[Int]): Int = ds.foldLeft(0)(_βŠ•_) extension (n: Int) def βŠ•(d Int): Int = 10 * n + d π’…π’†π’„π’Šπ’Žπ’‚π’ 1,2,3,4 = 𝑑0 βˆ— 103 + (𝑑1 βˆ— 102 + (𝑑2 βˆ— 101 + (𝑑3 βˆ— 100 + 0))) = 1 βˆ— 1000 + (2 βˆ— 100 + (3 βˆ— 10 + (4 βˆ— 1 + 0))) = 1234 π’…π’†π’„π’Šπ’Žπ’‚π’ 1,2,3,4 = 10 βˆ— 10 βˆ— 10 βˆ— 10 βˆ— 0 + 𝑑0 + 𝑑1 + 𝑑2 + 𝑑3 = 10 βˆ— (10 βˆ— 10 βˆ— 10 βˆ— 0 + 1 + 2 + 3) + 4 = 1234