SlideShare a Scribd company logo
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

Array
ArrayArray
Teeing Up Python - Code Golf
Teeing Up Python - Code GolfTeeing Up Python - Code Golf
Teeing Up Python - Code Golf
Yelp Engineering
ย 
Lecture 01 reals number system
Lecture 01 reals number systemLecture 01 reals number system
Lecture 01 reals number system
Hazel 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.pptx
TseChris
ย 
Frp2016 3
Frp2016 3Frp2016 3
Frp2016 3
Kirill Kozlov
ย 
Complex function
Complex functionComplex function
Complex function
Shrey Patel
ย 
Maths number system
Maths   number systemMaths   number system
Maths number system
Sanjay Crรบzรฉ
ย 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
Aleksandras 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.pptx
Yagna15
ย 
Scala. Introduction to FP. Monads
Scala. Introduction to FP. MonadsScala. Introduction to FP. Monads
Scala. Introduction to FP. Monads
Kirill Kozlov
ย 
Python Lecture 11
Python Lecture 11Python Lecture 11
Python Lecture 11
Inzamam Baig
ย 
Monad Fact #4
Monad Fact #4Monad Fact #4
Monad Fact #4
Philip Schwarz
ย 
Ch8b
Ch8bCh8b
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
Stephan Janssen
ย 
7. basics
7. basics7. basics
7. basics
ExternalEvents
ย 
iRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat SheetiRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat Sheet
Samuel 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 Version
James Smith
ย 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
Daniel 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 #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a seriesFolding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a series
Philip Schwarz
ย 
Folding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a seriesFolding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a series
Philip Schwarz
ย 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
ย 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
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 Aid
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 series
Philip 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 series
Philip 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 series
Philip Schwarz
ย 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
Philip 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 Programs
Philip 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 Views
Philip 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 Scala
Philip 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 Scala
Philip 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 Scala
Philip Schwarz
ย 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
Philip 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 example
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 example
Philip 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
ย 

More from Philip Schwarz (20)

Folding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a seriesFolding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a series
ย 
Folding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a seriesFolding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a series
ย 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
ย 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
ย 
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...
ย 

Recently uploaded

Upturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in NashikUpturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in Nashik
Upturn India Technologies
ย 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
Luigi Fugaro
ย 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
Paul Brebner
ย 
Computer Science & Engineering VI Sem- New Syllabus.pdf
Computer Science & Engineering VI Sem- New Syllabus.pdfComputer Science & Engineering VI Sem- New Syllabus.pdf
Computer Science & Engineering VI Sem- New Syllabus.pdf
chandangoswami40933
ย 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
ย 
How GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdfHow GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdf
Zycus
ย 
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
ervikas4
ย 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
Pedro J. Molina
ย 
42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert
vaishalijagtap12
ย 
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
OnePlan Solutions
ย 
ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†
ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†
ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†
dakas1
ย 
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery FleetStork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
Vince Scalabrino
ย 
Building API data products on top of your real-time data infrastructure
Building API data products on top of your real-time data infrastructureBuilding API data products on top of your real-time data infrastructure
Building API data products on top of your real-time data infrastructure
confluent
ย 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
Yara Milbes
ย 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
kalichargn70th171
ย 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
ย 
็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘
็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘
็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘
widenerjobeyrl638
ย 
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptxOperational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
sandeepmenon62
ย 
Streamlining End-to-End Testing Automation
Streamlining End-to-End Testing AutomationStreamlining End-to-End Testing Automation
Streamlining End-to-End Testing Automation
Anand Bagmar
ย 

Recently uploaded (20)

Upturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in NashikUpturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in Nashik
ย 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
ย 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
ย 
Computer Science & Engineering VI Sem- New Syllabus.pdf
Computer Science & Engineering VI Sem- New Syllabus.pdfComputer Science & Engineering VI Sem- New Syllabus.pdf
Computer Science & Engineering VI Sem- New Syllabus.pdf
ย 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
ย 
How GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdfHow GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdf
ย 
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
ย 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
ย 
42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert42 Ways to Generate Real Estate Leads - Sellxpert
42 Ways to Generate Real Estate Leads - Sellxpert
ย 
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
ย 
ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†
ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†
ไธ€ๆฏ”ไธ€ๅŽŸ็‰ˆ(USFๆฏ•ไธš่ฏ)ๆ—ง้‡‘ๅฑฑๅคงๅญฆๆฏ•ไธš่ฏๅฆ‚ไฝ•ๅŠž็†
ย 
bgiolcb
bgiolcbbgiolcb
bgiolcb
ย 
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery FleetStork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
ย 
Building API data products on top of your real-time data infrastructure
Building API data products on top of your real-time data infrastructureBuilding API data products on top of your real-time data infrastructure
Building API data products on top of your real-time data infrastructure
ย 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
ย 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
ย 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
ย 
็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘
็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘
็พŽๆดฒๆฏ่ต”็Ž‡ๆŠ•ๆณจ็ฝ‘ใ€โ€‹็ฝ‘ๅ€โ€‹๐ŸŽ‰3977ยทEEโ€‹๐ŸŽ‰ใ€‘
ย 
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptxOperational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
ย 
Streamlining End-to-End Testing Automation
Streamlining End-to-End Testing AutomationStreamlining End-to-End Testing Automation
Streamlining End-to-End Testing Automation
ย 

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