SlideShare a Scribd company logo
1 of 33
Download to read offline
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

Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
John De Goes
 
Python Programming - IX. On Randomness
Python Programming - IX. On RandomnessPython Programming - IX. On Randomness
Python Programming - IX. On Randomness
Ranel Padon
 

What's hot (20)

O caml2014 leroy-slides
O caml2014 leroy-slidesO caml2014 leroy-slides
O caml2014 leroy-slides
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
 
A taste of Functional Programming
A taste of Functional ProgrammingA taste of Functional Programming
A taste of Functional Programming
 
Advanced JavaScript
Advanced JavaScript Advanced JavaScript
Advanced JavaScript
 
Programming in Scala: Notes
Programming in Scala: NotesProgramming in Scala: Notes
Programming in Scala: Notes
 
Clojure intro
Clojure introClojure intro
Clojure intro
 
Knolx session
Knolx sessionKnolx session
Knolx session
 
Functional solid
Functional solidFunctional solid
Functional solid
 
Functional Programming in Scala
Functional Programming in ScalaFunctional Programming in Scala
Functional Programming in Scala
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
 
Ankara Jug - Practical Functional Programming with Scala
Ankara Jug - Practical Functional Programming with ScalaAnkara Jug - Practical Functional Programming with Scala
Ankara Jug - Practical Functional Programming with Scala
 
Functional programming in JavaScript
Functional programming in JavaScriptFunctional programming in JavaScript
Functional programming in JavaScript
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect System
 
Hey! There's OCaml in my Rust!
Hey! There's OCaml in my Rust!Hey! There's OCaml in my Rust!
Hey! There's OCaml in my Rust!
 
Clojure basics
Clojure basicsClojure basics
Clojure basics
 
Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++
 
Python Programming - IX. On Randomness
Python Programming - IX. On RandomnessPython Programming - IX. On Randomness
Python Programming - IX. On Randomness
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
 
Functional Programming in Javascript - IL Tech Talks week
Functional Programming in Javascript - IL Tech Talks weekFunctional Programming in Javascript - IL Tech Talks week
Functional Programming in Javascript - IL Tech Talks week
 
Scala categorytheory
Scala categorytheoryScala categorytheory
Scala categorytheory
 

Viewers also liked

Viewers also liked (20)

Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
7th AIS SigPrag International Conference on Pragmatic Web (ICPW 2012)
7th AIS SigPrag International Conference on Pragmatic Web (ICPW 2012)7th AIS SigPrag International Conference on Pragmatic Web (ICPW 2012)
7th AIS SigPrag International Conference on Pragmatic Web (ICPW 2012)
 
The Worst Code
The Worst CodeThe Worst Code
The Worst Code
 
What's up with the Pragmatic Web?
What's up with the Pragmatic Web?What's up with the Pragmatic Web?
What's up with the Pragmatic Web?
 
Running Containerized Node.js Services on AWS Elastic Beanstalk
Running Containerized Node.js Services on AWS Elastic BeanstalkRunning Containerized Node.js Services on AWS Elastic Beanstalk
Running Containerized Node.js Services on AWS Elastic Beanstalk
 
Functional Reactive Programming in JavaScript
Functional Reactive Programming in JavaScriptFunctional Reactive Programming in JavaScript
Functional Reactive Programming in JavaScript
 
Quality and Software Design Patterns
Quality and Software Design PatternsQuality and Software Design Patterns
Quality and Software Design Patterns
 
NetApp Industry Keynote - Flash Memory Summit - Aug2015
NetApp Industry Keynote - Flash Memory Summit - Aug2015NetApp Industry Keynote - Flash Memory Summit - Aug2015
NetApp Industry Keynote - Flash Memory Summit - Aug2015
 
GDGSCL - Docker a jeho provoz v Heroku a AWS
GDGSCL - Docker a jeho provoz v Heroku a AWSGDGSCL - Docker a jeho provoz v Heroku a AWS
GDGSCL - Docker a jeho provoz v Heroku a AWS
 
distributed: of systems and teams
distributed: of systems and teamsdistributed: of systems and teams
distributed: of systems and teams
 
Code Your Agility - Tips for Boosting Technical Agility in Your Organization
Code Your Agility - Tips for Boosting Technical Agility in Your OrganizationCode Your Agility - Tips for Boosting Technical Agility in Your Organization
Code Your Agility - Tips for Boosting Technical Agility in Your Organization
 
New Farming Methods in the Epistemological Wasteland of Application Security
New Farming Methods in the Epistemological Wasteland of Application SecurityNew Farming Methods in the Epistemological Wasteland of Application Security
New Farming Methods in the Epistemological Wasteland of Application Security
 
Threat Modeling for the Internet of Things
Threat Modeling for the Internet of ThingsThreat Modeling for the Internet of Things
Threat Modeling for the Internet of Things
 
Functional Programming Principles & Patterns
Functional Programming Principles & PatternsFunctional Programming Principles & Patterns
Functional Programming Principles & Patterns
 
Functional C++
Functional C++Functional C++
Functional C++
 
An Introduction to Software Testing
An Introduction to Software TestingAn Introduction to Software Testing
An Introduction to Software Testing
 
Software design methodologies
Software design methodologiesSoftware design methodologies
Software design methodologies
 
Lost in Motivation in an Agile World
Lost in Motivation in an Agile WorldLost in Motivation in an Agile World
Lost in Motivation in an Agile World
 
Startup Technology: Cheatsheet for Non-Techies
Startup Technology: Cheatsheet for Non-TechiesStartup Technology: Cheatsheet for Non-Techies
Startup Technology: Cheatsheet for Non-Techies
 
10 books that every developer must read
10 books that every developer must read10 books that every developer must read
10 books that every developer must read
 

Similar to Functional Programming Patterns for the Pragmatic Programmer

How to start functional programming (in Scala): Day1
How to start functional programming (in Scala): Day1How to start functional programming (in Scala): Day1
How to start functional programming (in Scala): Day1
Taisuke Oe
 
C programming session 08
C programming session 08C programming session 08
C programming session 08
Vivek Singh
 

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

Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional Patterns
 
Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and Effects
 
APSEC2020 Keynote
APSEC2020 KeynoteAPSEC2020 Keynote
APSEC2020 Keynote
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
Programming in Scala - Lecture Four
Programming in Scala - Lecture FourProgramming in Scala - Lecture Four
Programming in Scala - Lecture Four
 
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Thinking in Functions
Thinking in FunctionsThinking in Functions
Thinking in Functions
 
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
 
Beyond Mere Actors
Beyond Mere ActorsBeyond Mere Actors
Beyond Mere Actors
 
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
 
Rethink programming: a functional approach
Rethink programming: a functional approachRethink programming: a functional approach
Rethink programming: a functional approach
 
Fuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional ProgrammingFuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional Programming
 
How to start functional programming (in Scala): Day1
How to start functional programming (in Scala): Day1How to start functional programming (in Scala): Day1
How to start functional programming (in Scala): Day1
 
Functional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smartFunctional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smart
 
Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)
 
U19CS101 - PPS Unit 4 PPT (1).ppt
U19CS101 - PPS Unit 4 PPT (1).pptU19CS101 - PPS Unit 4 PPT (1).ppt
U19CS101 - PPS Unit 4 PPT (1).ppt
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
C programming session 08
C programming session 08C programming session 08
C programming session 08
 
Functional Scala
Functional ScalaFunctional Scala
Functional Scala
 
Lecture 4
Lecture 4Lecture 4
Lecture 4
 

Recently uploaded

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Recently uploaded (20)

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 

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