SlideShare a Scribd company logo
1 of 58
Download to read offline
Monoids, Monoids, Monoids
A fun ride through Abstract Algebra and Type Theory
Software Engineer at
CompStak
Maintainer of various
Typelevel libraries
Enthusiastic about FP
About me
● Monoids
● Monoids
● Monoids
● Monoids
Agenda
● Monoids
● Abstract Algebra
● Type Theory
Agenda
Monoids - Intro
trait Monoid[A] {
def empty: A
def combine(x: A, y: A): A
}
implicit val monoidInt: Monoid[Int] = new Monoid[Int] {
def empty: Int = 0
def combine(a: Int, b: Int): Int = a + b
}
Monoids
def combineInts(list: List[Int]): Int =
list.foldLeft(0)(_ + _)
def combineStrings(list: List[String]): String =
list.foldLeft("")(_ + _)
def combineSets[T](list: List[Set[T]]): Set[T] =
list.foldLeft(Set.empty[T])(_ union _)
def combineAll[T: Monoid](list: List[T]): T =
list.foldLeft(Monoid[T].empty)(_ combine _)
Monoids everywhere
implicit def functionMonoid[A, B: Monoid] = new Monoid[A => B]
implicit def optionMonoid[A: Monoid]: Monoid[Option[A]]
implicit def tupleMonoid[A: Monoid, B: Monoid] = new Monoid[(A, B)]
implicit def mapMonoid[A, B: Monoid]: Monoid[Map[A, B]]
implicit def ioMonoid[A: Monoid]: Monoid[IO[A]]
And many more!
Monoids applied
def step(word: String) = (1, word.length, Map(word -> 1))
val (words, chars, occurrences) = data.foldMap(step)
val result = stream.scanMap(step)
Monoid laws
1. Associativity:
(x |+| y) |+| z === x |+| (y |+| z)
2. Right identity:
x |+| empty === x
3. Left identity:
empty |+| x === x
Associativity in action
(a |+| b |+| c |+| d |+| e |+| f |+| g)
↕
(a |+| b) |+| (c |+| d) |+| (e |+| f) |+| g
We can fully parallelize any associative operation!
Parallel aggregation
val stream: Stream[IO, A] = ...
val maxParallel: Int = getRunTime.availableProcessors
val result: IO[A] = stream.chunks
.mapAsync(maxParallel)(_.combineAll.pure[IO])
.compile
.foldMonoid
Algebraic laws
● Associativity
● Identity
● Invertibility
● Commutativity
● Idempotency
● Absorption
● Distributivity
cats-kernel
cats-kernel
Groups
trait Group[A] extends Monoid[A] {
def inverse(a: A): A
}
a |+| inverse(a) === empty
inverse(a) |+| a === empty
5 + (-5) === 0
4 * (¼) === 1
Set(1,2,3) symmetricDiff Set(1,2,3) === Set()
Groups
Groups
sealed trait NList[+A]
case class Add[A](a: A) extends NList[A]
case class Remove[A](a: A) extends NList[A]
case object Empty extends NList[Nothing]
case class Concat[A](x: NList[A], y: NList[A]) extends NList[A]
Semilattices
trait Semilattice[A] extends CommutativeSemigroup[A]
a |+| b === b |+| a
a |+| a === a
true && false === false && true
true && true === true
false && false === false
true || true === true
Set(1,2,3) union Set(1,2,3) === Set(1,2,3)
Set(1,2,3) intersect Set(1,2,3) === Set(1,2,3)
max(7, 7) === 7
Semilattices
Use cases:
● Consuming messages with At-Least-Once Delivery
● Geometry operations
● Independently updating state in a distributed System (CRDTs)
● Any situation you might need idempotency
cats-kernel
Algebraic laws
● Associativity ✅
● Identity ✅
● Invertibility ✅
● Commutativity ✅
● Idempotency ✅
● Absorption
● Distributivity
Ring-like structures
trait Semiring[A] {
def plus(x: A, y: A): A
def times(x: A, y: A): A
def zero: A
}
plus forms a commutative Monoid with zero as an identity
times forms a Semigroup
zero “absorbs” times:
a * 0 === 0
times “distributes” over plus:
a * (b + c) === (a * b) + (a * c)
Ring-like structures
Commutative additive monoid & multiplicative semigroup => Semiring
Commutative additive group & multiplicative semigroup => Rng
Commutative additive monoid & multiplicative monoid => Rig
Commutative additive group & multiplicative monoid => Ring
Commutative additive group & multiplicative group => Field
Lattices
Two Semilattices on the same type => Lattice
Two bounded Semilattices => Bounded Lattice
Two Semilattices that distribute over another => Distributive Lattice
Two bounded Semilattices that distribute over another =>
Bounded distributive Lattice
Monoids at the typelevel
So far we’ve talked about algebraic structures at the value level, but
in Scala we encounter them at the typelevel as well.
Product types are monoids
Associativity law:
(A, (B, C)) <-> ((A, B), C)
Identity laws:
(A, Unit) <-> A
(Unit, A) <-> A
Akin to the cartesian product of the set of inhabitants of the two types
Product types are monoids
Product types are monoids
Sum types are monoids
Associativity law:
Either[A, Either[B, C]] <-> Either[Either[A, B], C]
Identity laws:
Either[A, Nothing] <-> A
Either[Nothing, A] <-> A
Akin to the disjoint union of the set of inhabitants of the two types
Sum types are monoids
Sum types are monoids
How is this relevant?
trait Semigroupal[F[_]] {
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}
An abstract higher kinded semigroup, that merges two contexts inside a
product type.
trait Apply[F[_]] extends Semigroupal[F] with Functor[F] {
def ap[A, B](fa: F[A])(f: F[A => B]): F[B]
def product[A, B](fa: F[A])(fb: F[B]): F[(A, B)] =
ap(fa)(fb.map(b => a => (a, b)))
}
Apply is a Semigroupal functor
trait Monoidal[F[_]] extends Semigroupal[F] {
def unit: F[Unit]
}
An abstract higher kinded monoid, that uses the product type identity as
its own identity
trait Applicative[F[_]] extends Apply[F] with Monoidal[F] {
def pure[A](a: A): F[A]
def unit: F[Unit] =
pure(())
}
We can do the same with sum types
trait SumSemigroupal[F[_]] {
def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]]
}
trait SumMonoidal[F[_]] extends SumSemigroupal[F] {
def nothing: F[Nothing]
}
An abstract higher kinded monoid, that merges two contexts inside a sum
type.
We can do the same with sum types
trait SemigroupK[F[_]] {
def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]]
def combineK[A](x: F[A], y: F[A]): F[A] =
sum(x, y).map(_.merge)
}
trait MonoidK[F[_]] extends SemigroupK[F] {
def empty[A]: F[A]
}
Monoids for iteration
def foldMap[A, M: Monoid](fa: F[A])(f: A => M): M
def foldMapK[G[_]: MonoidK, A, B](fa: F[A])(f: A => G[B]): G[B]
def traverse[G[_]: Applicative, A, B](l: F[A])(f: A => G[B]): G[F[B]]
def foldMapM[G[_]: Monad, A, B: Monoid](fa: F[A])(f: A => G[B]): G[B]
Different formulation of the same laws
Monoid laws:
x |+| (y |+| z) === (x |+| y) |+| z
empty |+| x === x
Applicative laws:
a *> (b *> c) === (a *> b) *> c
pure(()) *> a === a
MonoidK laws:
a <+> (b <+> c) === (a <+> b) <+> c
empty <+> a === a
Monad laws:
fa >>= (a => f(a) >>= g) === (fa >>= f) >>= g
pure(()) >>= (_ => fa) === fa
Sum and product types form a commutative Rig 😮
type +[A, B] = Either[A, B]
type *[A, B] = (A, B)
type Zero = Nothing
type One = Unit
Absorption law:
A * Zero <-> Zero
Distributivity law:
A * (B + C) <-> (A * B) + (A * C)
Commutativity laws:
A + B <-> B + A
A * B <-> B * A
Sum and product types form a commutative Rig 😮
Alternative is a higher kinded Rig
trait Alternative[F[_]] {
def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]]
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
def pure[A](a: A): F[A]
def empty[A]: F[A]
}
Union types are bounded semilattices
Associativity law:
A | (B | C) =:= (A | B) | C
Identity law:
A | Nothing =:= A
Commutativity law:
A | B =:= B | A
Idempotency law:
A | A =:= A
Akin to the union of the set of inhabitants of the two types
Different equivalence relations
A =:= A | A
A <-> (A, Unit)
Difference between sum types and union types
Union types are bounded semilattices
Intersection types are bounded semilattices
Associativity law:
A & (B & C) =:= (A & B) & C
Identity law:
A & Any =:= A
Commutativity law:
A & B =:= B & A
Idempotency law:
A & A =:= A
Akin to the intersection of the set of inhabitants of the two types
Intersection types are bounded semilattices
Intersection types are bounded semilattices
Intersection types are bounded semilattices
Union and intersection types form a bounded distributive lattice 😮
Idempotency law:
A | A =:= A
A & A =:= A
Absorption laws:
A | Any =:= Any
A & Nothing =:= Nothing
Distributivity laws:
A | (B & C) =:= (A | B) & (A | C)
A & (B | C) =:= (A & B) | (A & C)
Union and intersection types form a bounded distributive lattice 😮
Union and intersection types form a bounded distributive lattice 😮
How is this useful?
trait UnionMonoidal[F[_]] extends Functor[F] {
def union[A, B](fa: F[A], fb: F[B]): F[A | B]
def empty[A]: F[A]
def combineK[A](x: F[A], y: F[A]): F[A] =
union(x, y)
def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] =
combineK(map(fa)(Left(_)), map(fb)(Right(_)))
}
How is this useful?
Either[Unit, A] <-> Option[A]
Either[Nothing, A] <-> A
(A, Unit) <-> A
ApplicativeError[F, Unit] ⇔ Alternative[F]
MonadError[F, Nothing] ⇔ Monad[F]
MonadWriter[F, Unit] ⇔ Monad[F]
How is this useful?
sealed trait GList[+A, +B] {
def head: A | B = ...
}
case class Nil[B](b: B) extends GList[Nothing, B]
// ...
type List[A] = GList[A, Unit]
type NonEmptyList[A] = GList[A, Nothing]
Other cool stuff
● MonadError is two monoids (monads) based on Either
● Parallel is two monoids with the same identity, so 0=1 (apparently
called a duoid, or united monoid)
● Categories are monoids too
● Cats-retry’s RetryPolicy is a Bounded Distributive Lattice
● Free and Cofree have the same structure except Free is based on
product types and Cofree on sum types
● Animations (Sequence and Parallel)
Conclusions
Today, we learned about different algebraic structures like
monoids, lattices, groups and rings and how we can use
higher kinded type classes to generalize some of these
concepts.
We also learned about some basic properties about Scala’s
type system and how it relates to these algebraic
structures.
Lastly, we also looked at some of the changes made to the
type system in the upcoming Scala 3 release.
We’re hiring!
Thank you for
listening!
Twitter: @LukaJacobowitz
GitHub: LukaJCB

More Related Content

What's hot

The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
John De Goes
 
Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)
stasimus
 
Introduction to Monads in Scala (2)
Introduction to Monads in Scala (2)Introduction to Monads in Scala (2)
Introduction to Monads in Scala (2)
stasimus
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
John De Goes
 

What's hot (20)

Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
 
Monoids - Part 2 - with examples using Scalaz and Cats
Monoids - Part 2 - with examples using Scalaz and CatsMonoids - Part 2 - with examples using Scalaz and Cats
Monoids - Part 2 - with examples using Scalaz and Cats
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Introduction to Monads in Scala (2)
Introduction to Monads in Scala (2)Introduction to Monads in Scala (2)
Introduction to Monads in Scala (2)
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generators
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
Why The Free Monad isn't Free
Why The Free Monad isn't FreeWhy The Free Monad isn't Free
Why The Free Monad isn't Free
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
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...
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
 
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
 
Functor Composition
Functor CompositionFunctor Composition
Functor Composition
 
Functions In Scala
Functions In Scala Functions In Scala
Functions In Scala
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystified
 

Similar to Monoids, Monoids, Monoids - ScalaLove 2020

Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami Patterns
Vasil Remeniuk
 
Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
Philip Schwarz
 

Similar to Monoids, Monoids, Monoids - ScalaLove 2020 (20)

The Essence of the Iterator Pattern
The Essence of the Iterator PatternThe Essence of the Iterator Pattern
The Essence of the Iterator Pattern
 
The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)
 
(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
 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami Patterns
 
Monoids
MonoidsMonoids
Monoids
 
Monoids
MonoidsMonoids
Monoids
 
Your data structures are made of maths!
Your data structures are made of maths!Your data structures are made of maths!
Your data structures are made of maths!
 
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...
 
Scala Type Classes: Basics and More
Scala Type Classes:  Basics and MoreScala Type Classes:  Basics and More
Scala Type Classes: Basics and More
 
Monad Fact #4
Monad Fact #4Monad Fact #4
Monad Fact #4
 
Monad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional ProgrammingMonad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional Programming
 
Thesis
ThesisThesis
Thesis
 
Thesis PPT
Thesis PPTThesis PPT
Thesis PPT
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
 
Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional Patterns
 
Category theory for beginners
Category theory for beginnersCategory theory for beginners
Category theory for beginners
 
Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
 
Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters - Piotr Parad...Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters - Piotr Parad...
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
 
Functors, in theory and in practice
Functors, in theory and in practiceFunctors, in theory and in practice
Functors, in theory and in practice
 

More from Luka Jacobowitz

What Referential Transparency can do for you
What Referential Transparency can do for youWhat Referential Transparency can do for you
What Referential Transparency can do for you
Luka Jacobowitz
 

More from Luka Jacobowitz (8)

Up and Running with the Typelevel Stack
Up and Running with the Typelevel StackUp and Running with the Typelevel Stack
Up and Running with the Typelevel Stack
 
Principled Error Handling - Scalapeño
Principled Error Handling - ScalapeñoPrincipled Error Handling - Scalapeño
Principled Error Handling - Scalapeño
 
Advanced Tagless Final - Saying Farewell to Free
Advanced Tagless Final - Saying Farewell to FreeAdvanced Tagless Final - Saying Farewell to Free
Advanced Tagless Final - Saying Farewell to Free
 
Building a Tagless Final DSL for WebGL
Building a Tagless Final DSL for WebGLBuilding a Tagless Final DSL for WebGL
Building a Tagless Final DSL for WebGL
 
What Referential Transparency can do for you
What Referential Transparency can do for youWhat Referential Transparency can do for you
What Referential Transparency can do for you
 
Scala UA 2017
Scala UA 2017Scala UA 2017
Scala UA 2017
 
Reactive Programming in the Browser feat. Scala.js and Rx
Reactive Programming in the Browser feat. Scala.js and RxReactive Programming in the Browser feat. Scala.js and Rx
Reactive Programming in the Browser feat. Scala.js and Rx
 
Reactive Programming in the Browser feat. Scala.js and PureScript
Reactive Programming in the Browser feat. Scala.js and PureScriptReactive Programming in the Browser feat. Scala.js and PureScript
Reactive Programming in the Browser feat. Scala.js and PureScript
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Recently uploaded (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 

Monoids, Monoids, Monoids - ScalaLove 2020

  • 1. Monoids, Monoids, Monoids A fun ride through Abstract Algebra and Type Theory
  • 2. Software Engineer at CompStak Maintainer of various Typelevel libraries Enthusiastic about FP About me
  • 3. ● Monoids ● Monoids ● Monoids ● Monoids Agenda
  • 4. ● Monoids ● Abstract Algebra ● Type Theory Agenda
  • 5. Monoids - Intro trait Monoid[A] { def empty: A def combine(x: A, y: A): A } implicit val monoidInt: Monoid[Int] = new Monoid[Int] { def empty: Int = 0 def combine(a: Int, b: Int): Int = a + b }
  • 6. Monoids def combineInts(list: List[Int]): Int = list.foldLeft(0)(_ + _) def combineStrings(list: List[String]): String = list.foldLeft("")(_ + _) def combineSets[T](list: List[Set[T]]): Set[T] = list.foldLeft(Set.empty[T])(_ union _) def combineAll[T: Monoid](list: List[T]): T = list.foldLeft(Monoid[T].empty)(_ combine _)
  • 7. Monoids everywhere implicit def functionMonoid[A, B: Monoid] = new Monoid[A => B] implicit def optionMonoid[A: Monoid]: Monoid[Option[A]] implicit def tupleMonoid[A: Monoid, B: Monoid] = new Monoid[(A, B)] implicit def mapMonoid[A, B: Monoid]: Monoid[Map[A, B]] implicit def ioMonoid[A: Monoid]: Monoid[IO[A]] And many more!
  • 8. Monoids applied def step(word: String) = (1, word.length, Map(word -> 1)) val (words, chars, occurrences) = data.foldMap(step) val result = stream.scanMap(step)
  • 9. Monoid laws 1. Associativity: (x |+| y) |+| z === x |+| (y |+| z) 2. Right identity: x |+| empty === x 3. Left identity: empty |+| x === x
  • 10. Associativity in action (a |+| b |+| c |+| d |+| e |+| f |+| g) ↕ (a |+| b) |+| (c |+| d) |+| (e |+| f) |+| g We can fully parallelize any associative operation!
  • 11. Parallel aggregation val stream: Stream[IO, A] = ... val maxParallel: Int = getRunTime.availableProcessors val result: IO[A] = stream.chunks .mapAsync(maxParallel)(_.combineAll.pure[IO]) .compile .foldMonoid
  • 12. Algebraic laws ● Associativity ● Identity ● Invertibility ● Commutativity ● Idempotency ● Absorption ● Distributivity
  • 15. Groups trait Group[A] extends Monoid[A] { def inverse(a: A): A } a |+| inverse(a) === empty inverse(a) |+| a === empty 5 + (-5) === 0 4 * (¼) === 1 Set(1,2,3) symmetricDiff Set(1,2,3) === Set()
  • 17. Groups sealed trait NList[+A] case class Add[A](a: A) extends NList[A] case class Remove[A](a: A) extends NList[A] case object Empty extends NList[Nothing] case class Concat[A](x: NList[A], y: NList[A]) extends NList[A]
  • 18. Semilattices trait Semilattice[A] extends CommutativeSemigroup[A] a |+| b === b |+| a a |+| a === a true && false === false && true true && true === true false && false === false true || true === true Set(1,2,3) union Set(1,2,3) === Set(1,2,3) Set(1,2,3) intersect Set(1,2,3) === Set(1,2,3) max(7, 7) === 7
  • 19. Semilattices Use cases: ● Consuming messages with At-Least-Once Delivery ● Geometry operations ● Independently updating state in a distributed System (CRDTs) ● Any situation you might need idempotency
  • 21. Algebraic laws ● Associativity ✅ ● Identity ✅ ● Invertibility ✅ ● Commutativity ✅ ● Idempotency ✅ ● Absorption ● Distributivity
  • 22. Ring-like structures trait Semiring[A] { def plus(x: A, y: A): A def times(x: A, y: A): A def zero: A } plus forms a commutative Monoid with zero as an identity times forms a Semigroup zero “absorbs” times: a * 0 === 0 times “distributes” over plus: a * (b + c) === (a * b) + (a * c)
  • 23. Ring-like structures Commutative additive monoid & multiplicative semigroup => Semiring Commutative additive group & multiplicative semigroup => Rng Commutative additive monoid & multiplicative monoid => Rig Commutative additive group & multiplicative monoid => Ring Commutative additive group & multiplicative group => Field
  • 24. Lattices Two Semilattices on the same type => Lattice Two bounded Semilattices => Bounded Lattice Two Semilattices that distribute over another => Distributive Lattice Two bounded Semilattices that distribute over another => Bounded distributive Lattice
  • 25. Monoids at the typelevel So far we’ve talked about algebraic structures at the value level, but in Scala we encounter them at the typelevel as well.
  • 26. Product types are monoids Associativity law: (A, (B, C)) <-> ((A, B), C) Identity laws: (A, Unit) <-> A (Unit, A) <-> A Akin to the cartesian product of the set of inhabitants of the two types
  • 27. Product types are monoids
  • 28. Product types are monoids
  • 29. Sum types are monoids Associativity law: Either[A, Either[B, C]] <-> Either[Either[A, B], C] Identity laws: Either[A, Nothing] <-> A Either[Nothing, A] <-> A Akin to the disjoint union of the set of inhabitants of the two types
  • 30. Sum types are monoids
  • 31. Sum types are monoids
  • 32. How is this relevant? trait Semigroupal[F[_]] { def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] } An abstract higher kinded semigroup, that merges two contexts inside a product type. trait Apply[F[_]] extends Semigroupal[F] with Functor[F] { def ap[A, B](fa: F[A])(f: F[A => B]): F[B] def product[A, B](fa: F[A])(fb: F[B]): F[(A, B)] = ap(fa)(fb.map(b => a => (a, b))) }
  • 33. Apply is a Semigroupal functor trait Monoidal[F[_]] extends Semigroupal[F] { def unit: F[Unit] } An abstract higher kinded monoid, that uses the product type identity as its own identity trait Applicative[F[_]] extends Apply[F] with Monoidal[F] { def pure[A](a: A): F[A] def unit: F[Unit] = pure(()) }
  • 34. We can do the same with sum types trait SumSemigroupal[F[_]] { def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] } trait SumMonoidal[F[_]] extends SumSemigroupal[F] { def nothing: F[Nothing] } An abstract higher kinded monoid, that merges two contexts inside a sum type.
  • 35. We can do the same with sum types trait SemigroupK[F[_]] { def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] def combineK[A](x: F[A], y: F[A]): F[A] = sum(x, y).map(_.merge) } trait MonoidK[F[_]] extends SemigroupK[F] { def empty[A]: F[A] }
  • 36. Monoids for iteration def foldMap[A, M: Monoid](fa: F[A])(f: A => M): M def foldMapK[G[_]: MonoidK, A, B](fa: F[A])(f: A => G[B]): G[B] def traverse[G[_]: Applicative, A, B](l: F[A])(f: A => G[B]): G[F[B]] def foldMapM[G[_]: Monad, A, B: Monoid](fa: F[A])(f: A => G[B]): G[B]
  • 37. Different formulation of the same laws Monoid laws: x |+| (y |+| z) === (x |+| y) |+| z empty |+| x === x Applicative laws: a *> (b *> c) === (a *> b) *> c pure(()) *> a === a MonoidK laws: a <+> (b <+> c) === (a <+> b) <+> c empty <+> a === a Monad laws: fa >>= (a => f(a) >>= g) === (fa >>= f) >>= g pure(()) >>= (_ => fa) === fa
  • 38. Sum and product types form a commutative Rig 😮 type +[A, B] = Either[A, B] type *[A, B] = (A, B) type Zero = Nothing type One = Unit Absorption law: A * Zero <-> Zero Distributivity law: A * (B + C) <-> (A * B) + (A * C) Commutativity laws: A + B <-> B + A A * B <-> B * A
  • 39. Sum and product types form a commutative Rig 😮
  • 40. Alternative is a higher kinded Rig trait Alternative[F[_]] { def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] def pure[A](a: A): F[A] def empty[A]: F[A] }
  • 41. Union types are bounded semilattices Associativity law: A | (B | C) =:= (A | B) | C Identity law: A | Nothing =:= A Commutativity law: A | B =:= B | A Idempotency law: A | A =:= A Akin to the union of the set of inhabitants of the two types
  • 42. Different equivalence relations A =:= A | A A <-> (A, Unit)
  • 43. Difference between sum types and union types
  • 44. Union types are bounded semilattices
  • 45. Intersection types are bounded semilattices Associativity law: A & (B & C) =:= (A & B) & C Identity law: A & Any =:= A Commutativity law: A & B =:= B & A Idempotency law: A & A =:= A Akin to the intersection of the set of inhabitants of the two types
  • 46. Intersection types are bounded semilattices
  • 47. Intersection types are bounded semilattices
  • 48. Intersection types are bounded semilattices
  • 49. Union and intersection types form a bounded distributive lattice 😮 Idempotency law: A | A =:= A A & A =:= A Absorption laws: A | Any =:= Any A & Nothing =:= Nothing Distributivity laws: A | (B & C) =:= (A | B) & (A | C) A & (B | C) =:= (A & B) | (A & C)
  • 50. Union and intersection types form a bounded distributive lattice 😮
  • 51. Union and intersection types form a bounded distributive lattice 😮
  • 52. How is this useful? trait UnionMonoidal[F[_]] extends Functor[F] { def union[A, B](fa: F[A], fb: F[B]): F[A | B] def empty[A]: F[A] def combineK[A](x: F[A], y: F[A]): F[A] = union(x, y) def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] = combineK(map(fa)(Left(_)), map(fb)(Right(_))) }
  • 53. How is this useful? Either[Unit, A] <-> Option[A] Either[Nothing, A] <-> A (A, Unit) <-> A ApplicativeError[F, Unit] ⇔ Alternative[F] MonadError[F, Nothing] ⇔ Monad[F] MonadWriter[F, Unit] ⇔ Monad[F]
  • 54. How is this useful? sealed trait GList[+A, +B] { def head: A | B = ... } case class Nil[B](b: B) extends GList[Nothing, B] // ... type List[A] = GList[A, Unit] type NonEmptyList[A] = GList[A, Nothing]
  • 55. Other cool stuff ● MonadError is two monoids (monads) based on Either ● Parallel is two monoids with the same identity, so 0=1 (apparently called a duoid, or united monoid) ● Categories are monoids too ● Cats-retry’s RetryPolicy is a Bounded Distributive Lattice ● Free and Cofree have the same structure except Free is based on product types and Cofree on sum types ● Animations (Sequence and Parallel)
  • 56. Conclusions Today, we learned about different algebraic structures like monoids, lattices, groups and rings and how we can use higher kinded type classes to generalize some of these concepts. We also learned about some basic properties about Scala’s type system and how it relates to these algebraic structures. Lastly, we also looked at some of the changes made to the type system in the upcoming Scala 3 release.
  • 58. Thank you for listening! Twitter: @LukaJacobowitz GitHub: LukaJCB