SlideShare ist ein Scribd-Unternehmen logo
1 von 8
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Ähnlich wie 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
 
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
 
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
 

Ähnlich wie 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
 

Mehr von Philip Schwarz

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip 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
 

Mehr von Philip Schwarz (20)

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
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...
 

Kürzlich hochgeladen

5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
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
 
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
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
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
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
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
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
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
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
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
 
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.
 
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
 
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.
 

Kürzlich hochgeladen (20)

5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
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-...
 
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
 
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
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
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
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
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...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
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...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
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
 
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 ...
 
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 🔝✔️✔️
 
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...
 

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