SlideShare a Scribd company logo
Functional Programming
Patterns
(for the pragmatic programmer)
~
@raulraja CTO @47deg
Acknowledgment
• Scalaz
• Rapture : Jon Pretty
• Miles Sabin : Shapeless
• Rúnar Bjarnason : Compositional Application
Architecture With Reasonably Priced Monads
• Noel Markham : A purely functional approach
to building large applications
• Jan Christopher Vogt : Tmaps
Functions are first class citizens in FP
Architecture
I want my main app services to strive for
• Composability
• Dependency Injection
• Interpretation
• Fault Tolerance
Composability
Composition gives us the power
to easily mix simple functions
to achieve more complex workflows.
Composability
We can achieve monadic function composition
with Kleisli Arrows
A M[B]
In other words a function that
for a given input it returns a type constructor…
List[B], Option[B], Either[B], Task[B],
Future[B]…
Composability
When the type constructor M[_] it's a Monad it
can be composed and sequenced in
for comprehensions
val composed = for {
a <- Kleisli((x : String) Option(x.toInt + 1))
b <- Kleisli((x : String) Option(x.toInt * 2))
} yield a + b
Composability
The deferred injection of the input parameter
enables
Dependency Injection
val composed = for {
a <- Kleisli((x : String) Option(x.toInt + 1))
b <- Kleisli((x : String) Option(x.toInt * 2))
} yield a + b
composed.run("1")
Composability : Kleisli
What about when the args are not of the same
type?
val composed = for {
a <- Kleisli((x : String) Option(x.toInt + 1))
b <- Kleisli((x : Int) Option(x * 2))
} yield a + b
Composability : Kleisli
By using Kleisli we just achieved
• Composability
• Dependency Injection
• Interpretation
• Fault Tolerance
Interpretation : Free Monads
What is a Free Monad?
-- A monad on a custom ADT that can be run
through an Interpreter
Interpretation : Free Monads
sealed trait Op[A]
case class Ask[A](a: () A) extends Op[A]
case class Async[A](a: () A) extends Op[A]
case class Tell(a: () Unit) extends Op[Unit]
Interpretation : Free Monads
What can you achieve with a custom ADT and
Free Monads?
def ask[A](a: A): OpMonad[A] = Free.liftFC(Ask(() a))
def async[A](a: A): OpMonad[A] = Free.liftFC(Async(() a))
def tell(a: Unit): OpMonad[Unit] = Free.liftFC(Tell(() a))
Interpretation : Free Monads
Functors and Monads for Free
(No need to manually implement map, flatMap,
etc...)
type OpMonad[A] = Free.FreeC[Op, A]
implicit val MonadOp: Monad[OpMonad] =
Free.freeMonad[({type λ[α] = Coyoneda[Op, α]})#λ]
Interpretation : Free Monads
At this point a program like this is nothing but
Data
describing the sequence of execution but FREE
of it's runtime interpretation.
val program = for {
a <- ask(1)
b <- async(2)
_ <- tell(println("log something"))
} yield a + b
Interpretation : Free Monads
We isolate interpretations
via Natural transformations AKA Interpreters.
In other words with map over
the outer type constructor Op
object ProdInterpreter extends (Op ~> Task) {
def apply[A](op: Op[A]) = op match {
case Ask(a) Task(a())
case Async(a) Task.fork(Task.delay(a()))
case Tell(a) Task.delay(a())
}
}
Interpretation : Free Monads
We can have different interpreters for our
production / test / experimental code.
object TestInterpreter extends (Op ~> Id.Id) {
def apply[A](op: Op[A]) = op match {
case Ask(a) a()
case Async(a) a()
case Tell(a) a()
}
}
Requirements
• Composability
• Dependency Injection
• Interpretation
• Fault Tolerance
Fault Tolerance
Most containers and patterns generalize to the
most common super-type or simply Throwable
loosing type information.
val f = scala.concurrent.Future.failed(new NumberFormatException)
val t = scala.util.Try(throw new NumberFormatException)
val d = for {
a <- 1.right[NumberFormatException]
b <- (new RuntimeException).left[Int]
} yield a + b
Fault Tolerance
We don't have to settle for Throwable!!!
We could use instead…
• Nested disjunctions
• Coproducts
• Delimited, Monadic, Dependently-typed,
Accumulating Checked Exceptions
Fault Tolerance : Dependently-
typed Acc Exceptions
Introducing rapture.core.Result
Fault Tolerance : Dependently-
typed Acc Exceptions
Result is similar to / but has 3 possible
outcomes
(Answer, Errata, Unforeseen)
val op = for {
a <- Result.catching[NumberFormatException]("1".toInt)
b <- Result.errata[Int, IllegalArgumentException](
new IllegalArgumentException("expected"))
} yield a + b
Fault Tolerance : Dependently-
typed Acc Exceptions
Result uses dependently typed monadic
exception accumulation
val op = for {
a <- Result.catching[NumberFormatException]("1".toInt)
b <- Result.errata[Int, IllegalArgumentException](
new IllegalArgumentException("expected"))
} yield a + b
Fault Tolerance : Dependently-
typed Acc Exceptions
You may recover by resolving errors to an
Answer.
op resolve (
each[IllegalArgumentException](_ 0),
each[NumberFormatException](_ 0),
each[IndexOutOfBoundsException](_ 0))
Fault Tolerance : Dependently-
typed Acc Exceptions
Or reconcile exceptions into a new custom
one.
case class MyCustomException(e : Exception) extends Exception(e.getMessage)
op reconcile (
each[IllegalArgumentException](MyCustomException(_)),
each[NumberFormatException](MyCustomException(_)),
each[IndexOutOfBoundsException](MyCustomException(_)))
Requirements
We have all the pieces we need
Let's put them together!
• Composability
• Dependency Injection
• Interpretation
• Fault Tolerance
Solving the Puzzle
How do we assemble a type that is:
Kleisli + Custom ADT + Result
for {
a <- Kleisli((x : String) ask(Result.catching[NumberFormatException](x.toInt)))
b <- Kleisli((x : String) ask(Result.catching[IllegalArgumentException](x.toInt)))
} yield a + b
We want a and b to be seen as Int but this won't
compile
because there are 3 nested monads
Solving the Puzzle : Monad
Transformers
Monad Transformers to the rescue!
type ServiceDef[D, A, B <: Exception] =
ResultT[({type λ[α] = ReaderT[OpMonad, D, α]})#λ, A, B]
Solving the Puzzle : Services
Two services with different dependencies
case class Converter() {
def convert(x: String): Int = x.toInt
}
case class Adder() {
def add(x: Int): Int = x + 1
}
case class Config(converter: Converter, adder: Adder)
val system = Config(Converter(), Adder())
Solving the Puzzle : Services
Two services with different dependencies
def service1(x : String) = Service { converter: Converter
ask(Result.catching[NumberFormatException](converter.convert(x)))
}
def service2 = Service { adder: Adder
ask(Result.catching[IllegalArgumentException](adder.add(22) + " added "))
}
Solving the Puzzle : Services
Two services with different dependencies
val composed = for {
a <- service1("1").liftD[Config]
b <- service2.liftD[Config]
} yield a + b
composed.exec(system)(TestInterpreter)
composed.exec(system)(ProdInterpreter)
Conclusion
• Composability : Kleisli
• Dependency Injection : Kleisli
• Interpretation : Free monads
• Fault Tolerance : Dependently typed
checked exceptions
Thanks!
@raulraja
@47deg
http://github.com/47deg/func-architecture

More Related Content

What's hot (20)

PDF
O caml2014 leroy-slides
OCaml
 
ODP
Functional Programming With Scala
Knoldus Inc.
 
PDF
A taste of Functional Programming
Jordan Open Source Association
 
PPTX
Advanced JavaScript
Zsolt Mészárovics
 
PDF
Programming in Scala: Notes
Roberto Casadei
 
PDF
Clojure intro
Basav Nagur
 
ODP
Knolx session
Knoldus Inc.
 
PDF
Functional solid
Matt Stine
 
PDF
Functional Programming in Scala
Bassam Abd El Hameed
 
PDF
Orthogonal Functional Architecture
John De Goes
 
PDF
Ankara Jug - Practical Functional Programming with Scala
Ensar Basri Kahveci
 
PPTX
Functional programming in JavaScript
Joseph Smith
 
PDF
The Design of the Scalaz 8 Effect System
John De Goes
 
PDF
Hey! There's OCaml in my Rust!
Kel Cecil
 
ODP
Clojure basics
Knoldus Inc.
 
PPTX
Systematic Generation Data and Types in C++
Sumant Tambe
 
PDF
Python Programming - IX. On Randomness
Ranel Padon
 
PDF
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Chris Richardson
 
PPTX
Functional Programming in Javascript - IL Tech Talks week
yoavrubin
 
PDF
Scala categorytheory
Knoldus Inc.
 
O caml2014 leroy-slides
OCaml
 
Functional Programming With Scala
Knoldus Inc.
 
A taste of Functional Programming
Jordan Open Source Association
 
Advanced JavaScript
Zsolt Mészárovics
 
Programming in Scala: Notes
Roberto Casadei
 
Clojure intro
Basav Nagur
 
Knolx session
Knoldus Inc.
 
Functional solid
Matt Stine
 
Functional Programming in Scala
Bassam Abd El Hameed
 
Orthogonal Functional Architecture
John De Goes
 
Ankara Jug - Practical Functional Programming with Scala
Ensar Basri Kahveci
 
Functional programming in JavaScript
Joseph Smith
 
The Design of the Scalaz 8 Effect System
John De Goes
 
Hey! There's OCaml in my Rust!
Kel Cecil
 
Clojure basics
Knoldus Inc.
 
Systematic Generation Data and Types in C++
Sumant Tambe
 
Python Programming - IX. On Randomness
Ranel Padon
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Chris Richardson
 
Functional Programming in Javascript - IL Tech Talks week
yoavrubin
 
Scala categorytheory
Knoldus Inc.
 

Viewers also liked (20)

PDF
Functional Programming Patterns (NDC London 2014)
Scott Wlaschin
 
PDF
7th AIS SigPrag International Conference on Pragmatic Web (ICPW 2012)
Adrian Paschke
 
PDF
The Worst Code
Michele Titolo
 
PDF
What's up with the Pragmatic Web?
CommunitySense
 
PDF
Running Containerized Node.js Services on AWS Elastic Beanstalk
zupzup.org
 
PDF
Functional Reactive Programming in JavaScript
zupzup.org
 
PDF
Quality and Software Design Patterns
Ptidej Team
 
PDF
NetApp Industry Keynote - Flash Memory Summit - Aug2015
Val Bercovici
 
PDF
GDGSCL - Docker a jeho provoz v Heroku a AWS
Ladislav Prskavec
 
PDF
distributed: of systems and teams
bridgetkromhout
 
PDF
Code Your Agility - Tips for Boosting Technical Agility in Your Organization
Lemi Orhan Ergin
 
PDF
New Farming Methods in the Epistemological Wasteland of Application Security
James Wickett
 
PDF
Threat Modeling for the Internet of Things
Eric Vétillard
 
PDF
Functional Programming Principles & Patterns
zupzup.org
 
PDF
Functional C++
Kevlin Henney
 
PDF
An Introduction to Software Testing
Thorsten Frommen
 
PPT
Software design methodologies
Dr. C.V. Suresh Babu
 
PDF
Lost in Motivation in an Agile World
Lemi Orhan Ergin
 
PDF
Startup Technology: Cheatsheet for Non-Techies
Freedactics
 
PDF
10 books that every developer must read
Ganesh Samarthyam
 
Functional Programming Patterns (NDC London 2014)
Scott Wlaschin
 
7th AIS SigPrag International Conference on Pragmatic Web (ICPW 2012)
Adrian Paschke
 
The Worst Code
Michele Titolo
 
What's up with the Pragmatic Web?
CommunitySense
 
Running Containerized Node.js Services on AWS Elastic Beanstalk
zupzup.org
 
Functional Reactive Programming in JavaScript
zupzup.org
 
Quality and Software Design Patterns
Ptidej Team
 
NetApp Industry Keynote - Flash Memory Summit - Aug2015
Val Bercovici
 
GDGSCL - Docker a jeho provoz v Heroku a AWS
Ladislav Prskavec
 
distributed: of systems and teams
bridgetkromhout
 
Code Your Agility - Tips for Boosting Technical Agility in Your Organization
Lemi Orhan Ergin
 
New Farming Methods in the Epistemological Wasteland of Application Security
James Wickett
 
Threat Modeling for the Internet of Things
Eric Vétillard
 
Functional Programming Principles & Patterns
zupzup.org
 
Functional C++
Kevlin Henney
 
An Introduction to Software Testing
Thorsten Frommen
 
Software design methodologies
Dr. C.V. Suresh Babu
 
Lost in Motivation in an Agile World
Lemi Orhan Ergin
 
Startup Technology: Cheatsheet for Non-Techies
Freedactics
 
10 books that every developer must read
Ganesh Samarthyam
 
Ad

Similar to Functional Programming Patterns for the Pragmatic Programmer (20)

PDF
Generic Functional Programming with Type Classes
Tapio Rautonen
 
PPTX
Monads and friends demystified
Alessandro Lacava
 
PDF
pure-functional-programming.pdf
PuneetChaturvedi23
 
PDF
The what over the how (another way on android development with kotlin)
Jose Manuel Pereira Garcia
 
PDF
Sequence and Traverse - Part 2
Philip Schwarz
 
PDF
What are monads?
José Luis García Hernández
 
PPTX
Advanced Functional Programming in Scala
Patrick Nicolas
 
PDF
Monads - Dublin Scala meetup
Mikhail Girkin
 
PDF
Functions, Types, Programs and Effects
Raymond Roestenburg
 
PDF
Enterprise Algebras, Scala World 2016
Timothy Perrett
 
PDF
Trends in Functional Programming Meng Wang
vahizqqe937
 
PPT
Thesis PPT
Drew Ferkin
 
PPT
Thesis
Drew Ferkin
 
PDF
Applicative Functor - Part 3
Philip Schwarz
 
PDF
It's All About Morphisms
Uberto Barbini
 
PDF
Drinking the free kool-aid
David Hoyt
 
PDF
Functional programming in Scala
Damian Jureczko
 
PDF
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
PDF
Practical cats
Raymond Tay
 
PDF
Stanfy MadCode Meetup #9: Functional Programming 101 with Swift
Stanfy
 
Generic Functional Programming with Type Classes
Tapio Rautonen
 
Monads and friends demystified
Alessandro Lacava
 
pure-functional-programming.pdf
PuneetChaturvedi23
 
The what over the how (another way on android development with kotlin)
Jose Manuel Pereira Garcia
 
Sequence and Traverse - Part 2
Philip Schwarz
 
Advanced Functional Programming in Scala
Patrick Nicolas
 
Monads - Dublin Scala meetup
Mikhail Girkin
 
Functions, Types, Programs and Effects
Raymond Roestenburg
 
Enterprise Algebras, Scala World 2016
Timothy Perrett
 
Trends in Functional Programming Meng Wang
vahizqqe937
 
Thesis PPT
Drew Ferkin
 
Thesis
Drew Ferkin
 
Applicative Functor - Part 3
Philip Schwarz
 
It's All About Morphisms
Uberto Barbini
 
Drinking the free kool-aid
David Hoyt
 
Functional programming in Scala
Damian Jureczko
 
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
Practical cats
Raymond Tay
 
Stanfy MadCode Meetup #9: Functional Programming 101 with Swift
Stanfy
 
Ad

Recently uploaded (20)

PDF
From Chaos to Clarity: Mastering Analytics Governance in the Modern Enterprise
Wiiisdom
 
PPTX
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
PPTX
Perfecting XM Cloud for Multisite Setup.pptx
Ahmed Okour
 
PDF
Transparency into Your Software’s True Reach
team-WIBU
 
PDF
>Wondershare Filmora Crack Free Download 2025
utfefguu
 
PDF
Dealing with JSON in the relational world
Andres Almiray
 
PPTX
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
PPTX
Cubase Pro Crack 2025 – Free Download Full Version with Activation Key
HyperPc soft
 
PDF
LPS25 - Operationalizing MLOps in GEP - Terradue.pdf
terradue
 
PDF
65811_Introducing the Fusion AI Agent Studio (1).pdf
g6129590
 
PDF
2025年 Linux 核心專題: 探討 sched_ext 及機器學習.pdf
Eric Chou
 
PDF
Continouous failure - Why do we make our lives hard?
Papp Krisztián
 
PPTX
computer forensics encase emager app exp6 1.pptx
ssuser343e92
 
PPTX
Android Notifications-A Guide to User-Facing Alerts in Android .pptx
Nabin Dhakal
 
PDF
The Rise of Sustainable Mobile App Solutions by New York Development Firms
ostechnologies16
 
PDF
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
PDF
Difference Between Kubernetes and Docker .pdf
Kindlebit Solutions
 
PPTX
CONCEPT OF PROGRAMMING in language .pptx
tamim41
 
PDF
Power BI vs Tableau vs Looker - Which BI Tool is Right for You?
MagnusMinds IT Solution LLP
 
PDF
Rewards and Recognition (2).pdf
ethan Talor
 
From Chaos to Clarity: Mastering Analytics Governance in the Modern Enterprise
Wiiisdom
 
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
Perfecting XM Cloud for Multisite Setup.pptx
Ahmed Okour
 
Transparency into Your Software’s True Reach
team-WIBU
 
>Wondershare Filmora Crack Free Download 2025
utfefguu
 
Dealing with JSON in the relational world
Andres Almiray
 
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
Cubase Pro Crack 2025 – Free Download Full Version with Activation Key
HyperPc soft
 
LPS25 - Operationalizing MLOps in GEP - Terradue.pdf
terradue
 
65811_Introducing the Fusion AI Agent Studio (1).pdf
g6129590
 
2025年 Linux 核心專題: 探討 sched_ext 及機器學習.pdf
Eric Chou
 
Continouous failure - Why do we make our lives hard?
Papp Krisztián
 
computer forensics encase emager app exp6 1.pptx
ssuser343e92
 
Android Notifications-A Guide to User-Facing Alerts in Android .pptx
Nabin Dhakal
 
The Rise of Sustainable Mobile App Solutions by New York Development Firms
ostechnologies16
 
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
Difference Between Kubernetes and Docker .pdf
Kindlebit Solutions
 
CONCEPT OF PROGRAMMING in language .pptx
tamim41
 
Power BI vs Tableau vs Looker - Which BI Tool is Right for You?
MagnusMinds IT Solution LLP
 
Rewards and Recognition (2).pdf
ethan Talor
 

Functional Programming Patterns for the Pragmatic Programmer

  • 1. Functional Programming Patterns (for the pragmatic programmer) ~ @raulraja CTO @47deg
  • 2. Acknowledgment • Scalaz • Rapture : Jon Pretty • Miles Sabin : Shapeless • Rúnar Bjarnason : Compositional Application Architecture With Reasonably Priced Monads • Noel Markham : A purely functional approach to building large applications • Jan Christopher Vogt : Tmaps
  • 3. Functions are first class citizens in FP Architecture
  • 4. I want my main app services to strive for • Composability • Dependency Injection • Interpretation • Fault Tolerance
  • 5. Composability Composition gives us the power to easily mix simple functions to achieve more complex workflows.
  • 6. Composability We can achieve monadic function composition with Kleisli Arrows A M[B] In other words a function that for a given input it returns a type constructor… List[B], Option[B], Either[B], Task[B], Future[B]…
  • 7. Composability When the type constructor M[_] it's a Monad it can be composed and sequenced in for comprehensions val composed = for { a <- Kleisli((x : String) Option(x.toInt + 1)) b <- Kleisli((x : String) Option(x.toInt * 2)) } yield a + b
  • 8. Composability The deferred injection of the input parameter enables Dependency Injection val composed = for { a <- Kleisli((x : String) Option(x.toInt + 1)) b <- Kleisli((x : String) Option(x.toInt * 2)) } yield a + b composed.run("1")
  • 9. Composability : Kleisli What about when the args are not of the same type? val composed = for { a <- Kleisli((x : String) Option(x.toInt + 1)) b <- Kleisli((x : Int) Option(x * 2)) } yield a + b
  • 10. Composability : Kleisli By using Kleisli we just achieved • Composability • Dependency Injection • Interpretation • Fault Tolerance
  • 11. Interpretation : Free Monads What is a Free Monad? -- A monad on a custom ADT that can be run through an Interpreter
  • 12. Interpretation : Free Monads sealed trait Op[A] case class Ask[A](a: () A) extends Op[A] case class Async[A](a: () A) extends Op[A] case class Tell(a: () Unit) extends Op[Unit]
  • 13. Interpretation : Free Monads What can you achieve with a custom ADT and Free Monads? def ask[A](a: A): OpMonad[A] = Free.liftFC(Ask(() a)) def async[A](a: A): OpMonad[A] = Free.liftFC(Async(() a)) def tell(a: Unit): OpMonad[Unit] = Free.liftFC(Tell(() a))
  • 14. Interpretation : Free Monads Functors and Monads for Free (No need to manually implement map, flatMap, etc...) type OpMonad[A] = Free.FreeC[Op, A] implicit val MonadOp: Monad[OpMonad] = Free.freeMonad[({type λ[α] = Coyoneda[Op, α]})#λ]
  • 15. Interpretation : Free Monads At this point a program like this is nothing but Data describing the sequence of execution but FREE of it's runtime interpretation. val program = for { a <- ask(1) b <- async(2) _ <- tell(println("log something")) } yield a + b
  • 16. Interpretation : Free Monads We isolate interpretations via Natural transformations AKA Interpreters. In other words with map over the outer type constructor Op object ProdInterpreter extends (Op ~> Task) { def apply[A](op: Op[A]) = op match { case Ask(a) Task(a()) case Async(a) Task.fork(Task.delay(a())) case Tell(a) Task.delay(a()) } }
  • 17. Interpretation : Free Monads We can have different interpreters for our production / test / experimental code. object TestInterpreter extends (Op ~> Id.Id) { def apply[A](op: Op[A]) = op match { case Ask(a) a() case Async(a) a() case Tell(a) a() } }
  • 18. Requirements • Composability • Dependency Injection • Interpretation • Fault Tolerance
  • 19. Fault Tolerance Most containers and patterns generalize to the most common super-type or simply Throwable loosing type information. val f = scala.concurrent.Future.failed(new NumberFormatException) val t = scala.util.Try(throw new NumberFormatException) val d = for { a <- 1.right[NumberFormatException] b <- (new RuntimeException).left[Int] } yield a + b
  • 20. Fault Tolerance We don't have to settle for Throwable!!! We could use instead… • Nested disjunctions • Coproducts • Delimited, Monadic, Dependently-typed, Accumulating Checked Exceptions
  • 21. Fault Tolerance : Dependently- typed Acc Exceptions Introducing rapture.core.Result
  • 22. Fault Tolerance : Dependently- typed Acc Exceptions Result is similar to / but has 3 possible outcomes (Answer, Errata, Unforeseen) val op = for { a <- Result.catching[NumberFormatException]("1".toInt) b <- Result.errata[Int, IllegalArgumentException]( new IllegalArgumentException("expected")) } yield a + b
  • 23. Fault Tolerance : Dependently- typed Acc Exceptions Result uses dependently typed monadic exception accumulation val op = for { a <- Result.catching[NumberFormatException]("1".toInt) b <- Result.errata[Int, IllegalArgumentException]( new IllegalArgumentException("expected")) } yield a + b
  • 24. Fault Tolerance : Dependently- typed Acc Exceptions You may recover by resolving errors to an Answer. op resolve ( each[IllegalArgumentException](_ 0), each[NumberFormatException](_ 0), each[IndexOutOfBoundsException](_ 0))
  • 25. Fault Tolerance : Dependently- typed Acc Exceptions Or reconcile exceptions into a new custom one. case class MyCustomException(e : Exception) extends Exception(e.getMessage) op reconcile ( each[IllegalArgumentException](MyCustomException(_)), each[NumberFormatException](MyCustomException(_)), each[IndexOutOfBoundsException](MyCustomException(_)))
  • 26. Requirements We have all the pieces we need Let's put them together! • Composability • Dependency Injection • Interpretation • Fault Tolerance
  • 27. Solving the Puzzle How do we assemble a type that is: Kleisli + Custom ADT + Result for { a <- Kleisli((x : String) ask(Result.catching[NumberFormatException](x.toInt))) b <- Kleisli((x : String) ask(Result.catching[IllegalArgumentException](x.toInt))) } yield a + b We want a and b to be seen as Int but this won't compile because there are 3 nested monads
  • 28. Solving the Puzzle : Monad Transformers Monad Transformers to the rescue! type ServiceDef[D, A, B <: Exception] = ResultT[({type λ[α] = ReaderT[OpMonad, D, α]})#λ, A, B]
  • 29. Solving the Puzzle : Services Two services with different dependencies case class Converter() { def convert(x: String): Int = x.toInt } case class Adder() { def add(x: Int): Int = x + 1 } case class Config(converter: Converter, adder: Adder) val system = Config(Converter(), Adder())
  • 30. Solving the Puzzle : Services Two services with different dependencies def service1(x : String) = Service { converter: Converter ask(Result.catching[NumberFormatException](converter.convert(x))) } def service2 = Service { adder: Adder ask(Result.catching[IllegalArgumentException](adder.add(22) + " added ")) }
  • 31. Solving the Puzzle : Services Two services with different dependencies val composed = for { a <- service1("1").liftD[Config] b <- service2.liftD[Config] } yield a + b composed.exec(system)(TestInterpreter) composed.exec(system)(ProdInterpreter)
  • 32. Conclusion • Composability : Kleisli • Dependency Injection : Kleisli • Interpretation : Free monads • Fault Tolerance : Dependently typed checked exceptions