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

PDF
Monad Fact #4
PDF
Monoids - Part 1 - with examples using Scalaz and Cats
PDF
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
PDF
Monoids - Part 2 - with examples using Scalaz and Cats
PDF
Simple IO Monad in 'Functional Programming in Scala'
PDF
Monad Transformers - Part 1
PDF
Abstracting over the Monad yielded by a for comprehension and its generators
PDF
Functors
Monad Fact #4
Monoids - Part 1 - with examples using Scalaz and Cats
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
Monoids - Part 2 - with examples using Scalaz and Cats
Simple IO Monad in 'Functional Programming in Scala'
Monad Transformers - Part 1
Abstracting over the Monad yielded by a for comprehension and its generators
Functors

What's hot (20)

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

Similar to Monad Fact #2 (17)

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

More from Philip Schwarz (20)

PDF
ApplicativeError functions handling and recovering from errors: A mnemonic to...
PDF
Folding Cheat Sheet Series Titles - a series of 9 decks
PDF
Folding Cheat Sheet # 9 - List Unfolding 𝑢𝑛𝑓𝑜𝑙𝑑 as the Computational Dual of ...
PDF
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
PDF
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
PDF
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
PDF
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
PDF
The Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
PDF
The Open-Closed Principle - Part 1 - The Original Version
PDF
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
PDF
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
PDF
Fibonacci Function Gallery - Part 2 - One in a series
PDF
Fibonacci Function Gallery - Part 1 (of a series) - with minor corrections
PDF
Fibonacci Function Gallery - Part 1 (of a series)
PDF
The Debt Metaphor - Ward Cunningham in his 2009 YouTube video
PDF
Folding Cheat Sheet Series Titles (so far)
PDF
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
PDF
Folding Cheat Sheet #8 - eighth in a series
PDF
Function Applicative for Great Good of Leap Year Function
PDF
Folding Cheat Sheet #7 - seventh in a series
ApplicativeError functions handling and recovering from errors: A mnemonic to...
Folding Cheat Sheet Series Titles - a series of 9 decks
Folding Cheat Sheet # 9 - List Unfolding 𝑢𝑛𝑓𝑜𝑙𝑑 as the Computational Dual of ...
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
The Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
The Open-Closed Principle - Part 1 - The Original Version
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Fibonacci Function Gallery - Part 2 - One in a series
Fibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Fibonacci Function Gallery - Part 1 (of a series)
The Debt Metaphor - Ward Cunningham in his 2009 YouTube video
Folding Cheat Sheet Series Titles (so far)
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
Folding Cheat Sheet #8 - eighth in a series
Function Applicative for Great Good of Leap Year Function
Folding Cheat Sheet #7 - seventh in a series

Recently uploaded (20)

PPTX
"Secure File Sharing Solutions on AWS".pptx
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PDF
Website Design Services for Small Businesses.pdf
PPTX
Introduction to Windows Operating System
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPTX
Cybersecurity: Protecting the Digital World
PDF
Topaz Photo AI Crack New Download (Latest 2025)
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
STL Containers in C++ : Sequence Container : Vector
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
PPTX
assetexplorer- product-overview - presentation
PDF
Ableton Live Suite for MacOS Crack Full Download (Latest 2025)
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PPTX
Custom Software Development Services.pptx.pptx
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
"Secure File Sharing Solutions on AWS".pptx
DNT Brochure 2025 – ISV Solutions @ D365
Website Design Services for Small Businesses.pdf
Introduction to Windows Operating System
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Cybersecurity: Protecting the Digital World
Topaz Photo AI Crack New Download (Latest 2025)
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
Autodesk AutoCAD Crack Free Download 2025
STL Containers in C++ : Sequence Container : Vector
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
assetexplorer- product-overview - presentation
Ableton Live Suite for MacOS Crack Full Download (Latest 2025)
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
Advanced SystemCare Ultimate Crack + Portable (2025)
Custom Software Development Services.pptx.pptx
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...

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