SlideShare a Scribd company logo
1 of 9
Download to read offline
MONAD FACT #2
@philip_schwarzslides by
https://www.slideshare.net/pjschwarz
equivalence of nested flatMaps and chained flatMaps
for Kleisli arrow composition
Kleisli arrows are functions of types like A => M[B], where M is a monadic type constructor.
Consider three Kleisli arrows f, g and h:
f: A => M[B]
g: B => M[C]
h: C => M[D]
A convenient way of composing f, g and h in Scala is by using a for comprehension:
for {
b <- f(a)
c <- g(b)
d <- h(c)
} yield d
On the next slide we look at a concrete (if contrived) example.
@philip_schwarz
case class Company(name: String)
case class Driver(name: String)
case class Car(registration: String)
val ibmCompany = Company(name="IBM")
val axaCompany = Company(name="AXA")
val driverJohnSmith = Driver(name="John Smith")
val carRegisteredABC123 = Car(registration="ABC123")
val driverByCompany = Map( ibmCompany -> driverJohnSmith )
val carByDriver = Map( driverJohnSmith -> carRegisteredABC123 )
val insuranceByCar = Map( carRegisteredABC123 -> axaCompany )
val f: Company => Option[Driver] = company => driverByCompany.get(company)
val g: Driver => Option[Car] = driver => carByDriver.get(driver)
val h: Car => Option[Company] = car => insuranceByCar.get(car)
def fgh: Company => Option[Company] = company =>
for {
driver <- f(company)
car <- g(driver)
insurance <- h(car)
} yield insurance
Our domain consists of companies, drivers and cars.
Here are a multinational information technology
company, an insurance company, a driver and a car.
The CEO of IBM has a driver
whose car is insured by AXA.
Here are our three Kleisli arrows: f, g and h. They
return a monad whose type constructor is Option.
Better names for Kleisli arrows f, g and h could be
the following:
• getCEODriverOf(company)
• getCarDrivenBy(driver)
• getInsurerFor(car)
But for our purposes we can forget what the
functions are computing and just concentrate on
the fact that they are Kleisli arrows.
Here is function fgh, a
Kleisli arrow that is the
composition of f, g and h.
assert( fgh(ibmCompany) == Some(Company("AXA")) )
assert( fgh(axaCompany) == None )
Here we test that the insurer of the car driven by the driver of IBM’s CEO is AXA.
There is no insurer of the car driven by the driver of AXA’s CEO (no such car nor driver).
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver)
.flatMap { car => h(car)
.map { insurance => insurance
}
}
}
val fgh : Company => Option[Company] = company =>
for {
driver <- f(company)
car <- g(driver)
insurance <- h(car)
} yield insurance
As we saw in MONAD FACT #1, the code on the left desugars to the code on the right
Mapped function insurance => insurance
is just the identity function
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver)
.flatMap { car => h(car)
.map { identity
}
}
}
The reason why a monad has a map function is that every
monad is also a functor. The map function of a functor is subject
to the following functor law:
map(x)(identity) == x.
Thanks to this law, we can simplify our code by dropping the
invocation of map.
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver)
.flatMap { car => h(car)
}
}
desugars to
simplified
At this point we can go one of two ways.
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver)
.flatMap { car => h(car)
}
}
val fgh : Company => Option[Company] = company =>
f(company) flatMap { driver => g(driver) flatMap h }
We can simplify the above just a little by making it less verbose
Later on I’ll refer to this as
the nested flatMap function.
Or alternatively, it turns out that (see later) we can rearrange the
flatMap invocations so that rather than being nested, they are chained.
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver)
.flatMap { car => h(car)
}
}
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver) }
.flatMap { car => h(car) }
assert( fgh(ibmCompany) == Some(Company("AXA")) )
assert( fgh(axaCompany) == None )
to chained
flatMaps
from nested
flatMaps
@philip_schwarz
val fgh : Company => Option[Company] = company =>
f(company)
.flatMap { driver => g(driver) }
.flatMap { car => h(car) }
And finally, we can simplify this a bit
val fgh: Company => Option[Company] = company =>
f(company) flatMap g flatMap h
On the next slide, I’ll be referring to the above
function as the chained flatMap function
by making it less verbose
simplified
val fgh : Company => Option[Company] = company =>
for {
driver <- f(company)
car <- g(driver)
insurance <- h(car)
} yield insurance
val fgh : Company => Option[Company] = company =>
f(company) flatMap { driver => g(driver) flatMap h }
val fgh: Company => Option[Company] = company =>
f(company) flatMap g flatMap h
Monadic Law of Associativity
(m flatMap f) flatMap g ≡ m flatMap ( x => f(x) flatMap g )
This holds for all values m, f and g of the appropriate types (see right).
While on the left hand side of the equation the invocations of flatMap are being chained, on the
right hand side of the equation the invocations are being nested.
The two desugared versions of the for comprehension function are equivalent because
the flatMap function of a monad is subject to a monadic Law of Associativity:
an operation ✽ is associative if it doesn’t
matter whether we parenthesize it
( (x ✽ y) ✽ z) or (x ✽ (y ✽ z) )
f: A => M[B]
g: B => M[C]
h: C => M[D]
nested flatMap functionchained flatMap function
for comprehension function
e.g. in our example we have the following:
(f(a) flatMap g) flatMap h ≡ f(a) flatMap ( b => g(b) flatMap h )
m: M[A]
f: A => M[B]
g: B => M[C]
We started off with the
for comprehension
function on the right
And we refactored
it into the two
equivalent
desugared
functions below
@philip_schwarz
assert(
((company:Company) => f(company) flatMap g flatMap h)(ibmCompany) // chained flatMaps
== ((company:Company) => f(company) flatMap { driver => g(driver) flatMap h } )(ibmCompany) // nested flatMaps
)
assert(
// desugars to nested flatMaps and map
((company: Company) =>
for {
driver <- f(company)
car <- g(driver)
insurance <- h(car)
} yield insurance)
(ibmCompany)
==
(Some(Company("AXA")))
)
assert(
((company: Company) =>
for {
driver <- f(company)
car <- g(driver)
insurance <- h(car)
} yield insurance)
(ibmCompany)
==
// chained flatMaps
((company: Company) => f(company) flatMap g flatMap h )
(ibmCompany)
)
assert(
((company: Company) =>
for {
driver <- f(company)
car <- g(driver)
insurance <- h(car)
} yield insurance)
(ibmCompany)
==
// nested flatMaps
((company:Company) => f(company) flatMap { driver => g(driver) flatMap h } )
(ibmCompany)
)
Monadic Law of Associativity
(m flatMap f) flatMap g ≡ m flatMap ( x => f(x) flatMap g )
The Monadic Law of Associativity in the context of this example
(f(a) flatMap g) flatMap h ≡ f(a) flatMap ( b => g(b) flatMap h )
f: A => M[B]
g: B => M[C]
h: C => M[D]
Here is a recap
m: M[A]
f: A => M[B]
g: B => M[C]
See the following for the list of all available slide decks in the MONAD FACT series
https://www.slideshare.net/pjschwarz/the-monad-fact-slide-deck-series

More Related Content

What's hot

Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
Philip Schwarz
 

What's hot (20)

Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaFunctional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
 
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and ScalaSierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
 
Applicative Functor - Part 3
Applicative Functor - Part 3Applicative Functor - Part 3
Applicative Functor - Part 3
 
Function Composition - forward composition versus backward composition
Function Composition - forward composition versus backward compositionFunction Composition - forward composition versus backward composition
Function Composition - forward composition versus backward composition
 
Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
 
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
 
Functor Composition
Functor CompositionFunctor Composition
Functor Composition
 
Scala collection methods flatMap and flatten are more powerful than monadic f...
Scala collection methods flatMap and flatten are more powerful than monadic f...Scala collection methods flatMap and flatten are more powerful than monadic f...
Scala collection methods flatMap and flatten are more powerful than monadic f...
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
 
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
Scala 3 enum for a terser Option Monad Algebraic Data Type
Scala 3 enum for a terser Option Monad Algebraic Data TypeScala 3 enum for a terser Option Monad Algebraic Data Type
Scala 3 enum for a terser Option Monad Algebraic Data Type
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and ScalaFolding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala
 
Introducing Assignment invalidates the Substitution Model of Evaluation and v...
Introducing Assignment invalidates the Substitution Model of Evaluation and v...Introducing Assignment invalidates the Substitution Model of Evaluation and v...
Introducing Assignment invalidates the Substitution Model of Evaluation and v...
 
Functor Laws
Functor LawsFunctor Laws
Functor Laws
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
 
Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Sequence and Traverse - Part 3
Sequence and Traverse - Part 3
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
 

Similar to Monad Fact #2

Functions & Procedures [7]
Functions & Procedures [7]Functions & Procedures [7]
Functions & Procedures [7]
ecko_disasterz
 
No more loops with lambdaj
No more loops with lambdajNo more loops with lambdaj
No more loops with lambdaj
Mario Fusco
 
For the following questions, you will implement the data structure to.pdf
For the following questions, you will implement the data structure to.pdfFor the following questions, you will implement the data structure to.pdf
For the following questions, you will implement the data structure to.pdf
arjunhassan8
 

Similar to Monad Fact #2 (17)

for and flatMap - a close look
for and flatMap - a close lookfor and flatMap - a close look
for and flatMap - a close look
 
Functions & Procedures [7]
Functions & Procedures [7]Functions & Procedures [7]
Functions & Procedures [7]
 
(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads
 
Essence of the iterator pattern
Essence of the iterator patternEssence of the iterator pattern
Essence of the iterator pattern
 
Informatics Practices/ Information Practices Project (IP Project Class 12)
Informatics Practices/ Information Practices Project (IP Project Class 12)Informatics Practices/ Information Practices Project (IP Project Class 12)
Informatics Practices/ Information Practices Project (IP Project Class 12)
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetup
 
No more loops with lambdaj
No more loops with lambdajNo more loops with lambdaj
No more loops with lambdaj
 
List-based Monadic Computations for Dynamic Languages
List-based Monadic Computations for Dynamic LanguagesList-based Monadic Computations for Dynamic Languages
List-based Monadic Computations for Dynamic Languages
 
Module 2 topic 2 notes
Module 2 topic 2 notesModule 2 topic 2 notes
Module 2 topic 2 notes
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
MonadicJava_-_reviwed.pdf
MonadicJava_-_reviwed.pdfMonadicJava_-_reviwed.pdf
MonadicJava_-_reviwed.pdf
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
Practical scalaz
Practical scalazPractical scalaz
Practical scalaz
 
For the following questions, you will implement the data structure to.pdf
For the following questions, you will implement the data structure to.pdfFor the following questions, you will implement the data structure to.pdf
For the following questions, you will implement the data structure to.pdf
 
XKE Typeclass
XKE TypeclassXKE Typeclass
XKE Typeclass
 

More from 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
 

More from 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 #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
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
 

Recently uploaded

Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
mbmh111980
 

Recently uploaded (20)

What need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java DevelopersWhat need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java Developers
 
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
 
Workforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdfWorkforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdf
 
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
KLARNA -  Language Models and Knowledge Graphs: A Systems ApproachKLARNA -  Language Models and Knowledge Graphs: A Systems Approach
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
 
A Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data MigrationA Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data Migration
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf
 
Secure Software Ecosystem Teqnation 2024
Secure Software Ecosystem Teqnation 2024Secure Software Ecosystem Teqnation 2024
Secure Software Ecosystem Teqnation 2024
 
how-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdfhow-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdf
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
Microsoft 365 Copilot; An AI tool changing the world of work _PDF.pdf
Microsoft 365 Copilot; An AI tool changing the world of work _PDF.pdfMicrosoft 365 Copilot; An AI tool changing the world of work _PDF.pdf
Microsoft 365 Copilot; An AI tool changing the world of work _PDF.pdf
 
Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 
5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
 
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product UpdatesGraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
AI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning FrameworkAI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning Framework
 
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
 
How to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabberHow to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabber
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 

Monad Fact #2

  • 1. MONAD FACT #2 @philip_schwarzslides by https://www.slideshare.net/pjschwarz equivalence of nested flatMaps and chained flatMaps for Kleisli arrow composition
  • 2. Kleisli arrows are functions of types like A => M[B], where M is a monadic type constructor. Consider three Kleisli arrows f, g and h: f: A => M[B] g: B => M[C] h: C => M[D] A convenient way of composing f, g and h in Scala is by using a for comprehension: for { b <- f(a) c <- g(b) d <- h(c) } yield d On the next slide we look at a concrete (if contrived) example. @philip_schwarz
  • 3. case class Company(name: String) case class Driver(name: String) case class Car(registration: String) val ibmCompany = Company(name="IBM") val axaCompany = Company(name="AXA") val driverJohnSmith = Driver(name="John Smith") val carRegisteredABC123 = Car(registration="ABC123") val driverByCompany = Map( ibmCompany -> driverJohnSmith ) val carByDriver = Map( driverJohnSmith -> carRegisteredABC123 ) val insuranceByCar = Map( carRegisteredABC123 -> axaCompany ) val f: Company => Option[Driver] = company => driverByCompany.get(company) val g: Driver => Option[Car] = driver => carByDriver.get(driver) val h: Car => Option[Company] = car => insuranceByCar.get(car) def fgh: Company => Option[Company] = company => for { driver <- f(company) car <- g(driver) insurance <- h(car) } yield insurance Our domain consists of companies, drivers and cars. Here are a multinational information technology company, an insurance company, a driver and a car. The CEO of IBM has a driver whose car is insured by AXA. Here are our three Kleisli arrows: f, g and h. They return a monad whose type constructor is Option. Better names for Kleisli arrows f, g and h could be the following: • getCEODriverOf(company) • getCarDrivenBy(driver) • getInsurerFor(car) But for our purposes we can forget what the functions are computing and just concentrate on the fact that they are Kleisli arrows. Here is function fgh, a Kleisli arrow that is the composition of f, g and h. assert( fgh(ibmCompany) == Some(Company("AXA")) ) assert( fgh(axaCompany) == None ) Here we test that the insurer of the car driven by the driver of IBM’s CEO is AXA. There is no insurer of the car driven by the driver of AXA’s CEO (no such car nor driver).
  • 4. val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) .flatMap { car => h(car) .map { insurance => insurance } } } val fgh : Company => Option[Company] = company => for { driver <- f(company) car <- g(driver) insurance <- h(car) } yield insurance As we saw in MONAD FACT #1, the code on the left desugars to the code on the right Mapped function insurance => insurance is just the identity function val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) .flatMap { car => h(car) .map { identity } } } The reason why a monad has a map function is that every monad is also a functor. The map function of a functor is subject to the following functor law: map(x)(identity) == x. Thanks to this law, we can simplify our code by dropping the invocation of map. val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) .flatMap { car => h(car) } } desugars to simplified
  • 5. At this point we can go one of two ways. val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) .flatMap { car => h(car) } } val fgh : Company => Option[Company] = company => f(company) flatMap { driver => g(driver) flatMap h } We can simplify the above just a little by making it less verbose Later on I’ll refer to this as the nested flatMap function. Or alternatively, it turns out that (see later) we can rearrange the flatMap invocations so that rather than being nested, they are chained. val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) .flatMap { car => h(car) } } val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) } .flatMap { car => h(car) } assert( fgh(ibmCompany) == Some(Company("AXA")) ) assert( fgh(axaCompany) == None ) to chained flatMaps from nested flatMaps @philip_schwarz
  • 6. val fgh : Company => Option[Company] = company => f(company) .flatMap { driver => g(driver) } .flatMap { car => h(car) } And finally, we can simplify this a bit val fgh: Company => Option[Company] = company => f(company) flatMap g flatMap h On the next slide, I’ll be referring to the above function as the chained flatMap function by making it less verbose simplified
  • 7. val fgh : Company => Option[Company] = company => for { driver <- f(company) car <- g(driver) insurance <- h(car) } yield insurance val fgh : Company => Option[Company] = company => f(company) flatMap { driver => g(driver) flatMap h } val fgh: Company => Option[Company] = company => f(company) flatMap g flatMap h Monadic Law of Associativity (m flatMap f) flatMap g ≡ m flatMap ( x => f(x) flatMap g ) This holds for all values m, f and g of the appropriate types (see right). While on the left hand side of the equation the invocations of flatMap are being chained, on the right hand side of the equation the invocations are being nested. The two desugared versions of the for comprehension function are equivalent because the flatMap function of a monad is subject to a monadic Law of Associativity: an operation ✽ is associative if it doesn’t matter whether we parenthesize it ( (x ✽ y) ✽ z) or (x ✽ (y ✽ z) ) f: A => M[B] g: B => M[C] h: C => M[D] nested flatMap functionchained flatMap function for comprehension function e.g. in our example we have the following: (f(a) flatMap g) flatMap h ≡ f(a) flatMap ( b => g(b) flatMap h ) m: M[A] f: A => M[B] g: B => M[C] We started off with the for comprehension function on the right And we refactored it into the two equivalent desugared functions below @philip_schwarz
  • 8. assert( ((company:Company) => f(company) flatMap g flatMap h)(ibmCompany) // chained flatMaps == ((company:Company) => f(company) flatMap { driver => g(driver) flatMap h } )(ibmCompany) // nested flatMaps ) assert( // desugars to nested flatMaps and map ((company: Company) => for { driver <- f(company) car <- g(driver) insurance <- h(car) } yield insurance) (ibmCompany) == (Some(Company("AXA"))) ) assert( ((company: Company) => for { driver <- f(company) car <- g(driver) insurance <- h(car) } yield insurance) (ibmCompany) == // chained flatMaps ((company: Company) => f(company) flatMap g flatMap h ) (ibmCompany) ) assert( ((company: Company) => for { driver <- f(company) car <- g(driver) insurance <- h(car) } yield insurance) (ibmCompany) == // nested flatMaps ((company:Company) => f(company) flatMap { driver => g(driver) flatMap h } ) (ibmCompany) ) Monadic Law of Associativity (m flatMap f) flatMap g ≡ m flatMap ( x => f(x) flatMap g ) The Monadic Law of Associativity in the context of this example (f(a) flatMap g) flatMap h ≡ f(a) flatMap ( b => g(b) flatMap h ) f: A => M[B] g: B => M[C] h: C => M[D] Here is a recap m: M[A] f: A => M[B] g: B => M[C]
  • 9. See the following for the list of all available slide decks in the MONAD FACT series https://www.slideshare.net/pjschwarz/the-monad-fact-slide-deck-series