SlideShare a Scribd company logo
1 of 25
Download to read offline
Reducing Boilerplate and Combining
Effects:
A Monad Transformer Example
Scala Matsuri - Feb 25th, 2017
Connie Chen
:
Hello
• @coni
• Data Platform team @ Twilio
• @ http://github.com/conniec
• Monad transformers allow different monads to
compose
• Combine effects of monads to create a
SUPER MONAD
• Eg. Future[Option], Future[Either],
Reader[Option]
• In this example, we will use the Cats library...
What are Monad transformers?
Future[Either[A, B]] turns into
EitherT[Future, A, B]
Future[Option[A]] turns into
OptionT[Future, A]
import scala.concurrent.Future
import cats.data.OptionT
import cats.implicits._
import
scala.concurrent.ExecutionContext.Implicits.glo
bal
case class Beans(fresh: Boolean = true)
case class Grounds()
class GroundBeansException(s: String) extends
Exception(s: String)
1.
Example: Making coffee!
Step 1. Grind the beans
def grindFreshBeans(beans: Beans, clumsy: Boolean =
false): Future[Option[Grounds]] = {
if (clumsy) {
Future.failed(new GroundBeansException("We are bad
at grinding"))
} else if (beans.fresh) {
Future.successful(Option(Grounds()))
} else {
Future.successful(None)
}
}
1.
Example: Making coffee!
Step 1. Grind the beans
Step 1. Grind the beans
Three different kind of results:
• Value found
• Value not found
• Future failed
Future 3
Example: Making coffee!
Step 2. Boil hot water
case class Kettle(filled: Boolean = true)
case class Water()
case class Coffee(delicious: Boolean)
class HotWaterException(s: String) extends
Exception(s: String)
2.
def getHotWater(kettle: Kettle, clumsy: Boolean =
false): Future[Option[Water]] = {
if (clumsy) {
Future.failed(new HotWaterException("Ouch
spilled that water!"))
} else if (kettle.filled) {
Future.successful(Option(Water()))
} else {
Future.successful(None)
}
}
Step 3. Combine water and coffee (it's a pourover)
3. ( )
def makingCoffee(grounds: Grounds, water: Water):
Future[Coffee] = {
println(s"Making coffee with... $grounds and
$water")
Future.successful(Coffee(delicious=true))
}
val coffeeFut = for {
} yield Option(result)
coffeeFut.onSuccess {
case Some(s) => println(s"SUCCESS: $s")
case None => println("No coffee found?")
}
coffeeFut.onFailure {
case x => println(s"FAIL: $x")
}
Without Monad transformers, success scenario
beans <- grindFreshBeans(Beans(fresh=true))
hotWater <- getHotWater(Kettle(filled=true))
beansResult = beans.getOrElse(throw new Exception("Beans result
errored. "))
waterResult = hotWater.getOrElse(throw new Exception("Water
result errored. "))
result <- makingCoffee(beansResult, waterResult)
Without Monad transformers, success scenario
coffeeFut:
scala.concurrent.Future[Option[Coffee]] =
scala.concurrent.impl.Promise
$DefaultPromise@7404ac2
scala> Making coffee with... Grounds() and
Water()
SUCCESS: Coffee(true)
With Monad transformers, success scenario
val coffeeFutMonadT = for {
beans <- OptionT(grindFreshBeans(Beans(fresh=true)))
hotWater <- OptionT(getHotWater(Kettle(filled=true)))
result <- OptionT.liftF(makingCoffee(beans, hotWater))
} yield result
coffeeFutMonadT.value.onSuccess {
case Some(s) => println(s"SUCCESS: $s")
case None => println("No coffee found?")
}
coffeeFutMonadT.value.onFailure {
case x => println(s"FAIL: $x")
}
coffeeFutMonadT:
cats.data.OptionT[scala.concurrent.Future,
Coffee] =
OptionT(scala.concurrent.impl.Promise
$DefaultPromise@4a1c4b40)
scala> Making coffee with... Grounds() and
Water()
SUCCESS: Coffee(true)
With Monad transformers, success scenario
OptionT
`fromOption` gives you an OptionT from Option
Internally, it is wrapping your option in a Future.successful()
`liftF` gives you an OptionT from Future
Internally, it is mapping on your Future and wrapping it in a
Some()
Helper functions on OptionT
val coffeeFut = for {
beans <- grindFreshBeans(Beans(fresh=false))
hotWater <- getHotWater(Kettle(filled=true))
beansResult = beans.getOrElse(throw new Exception("Beans result
errored. "))
waterResult = hotWater.getOrElse(throw new Exception("Water result
errored. "))
result <- makingCoffee(beansResult, waterResult)
} yield Option(result)
coffeeFut.onSuccess {
case Some(s) => println(s"SUCCESS: $s")
case None => println("No coffee found?")
}
coffeeFut.onFailure {
case x => println(s"FAIL: $x")
}
Without Monad transformers, failure scenario
Without Monad transformers, failure scenario
coffeeFut:
scala.concurrent.Future[Option[Coffee]] =
scala.concurrent.impl.Promise
$DefaultPromise@17ee3bd8
scala> FAIL: java.lang.Exception: Beans
result errored.
val coffeeFutT = for {
beans <- OptionT(grindFreshBeans(Beans(fresh=false)))
hotWater <- OptionT(getHotWater(Kettle(filled=true)))
result <- OptionT.liftF(makingCoffee(beans,
hotWater))
} yield result
coffeeFutT.value.onSuccess {
case Some(s) => println(s"SUCCESS: $s")
case None => println("No coffee found?")
}
coffeeFutT.value.onFailure {
case x => println(s"FAIL: $x")
}
With Monad transformers, failure scenario
With Monad transformers, failure scenario
coffeeFutT:
cats.data.OptionT[scala.concurrent.Future
,Coffee] =
OptionT(scala.concurrent.impl.Promise
$DefaultPromise@4e115bbc)
scala> No coffee found?
val coffeeFutT = for {
beans <- OptionT(grindFreshBeans(Beans(fresh=true)))
hotWater <- OptionT(getHotWater(Kettle(filled=true),
clumsy=true))
result <- OptionT.liftF(makingCoffee(beans,
hotWater))
} yield s"$result"
coffeeFutT.value.onSuccess {
case Some(s) => println(s"SUCCESS: $s")
case None => println("No coffee found?")
}
coffeeFutT.value.onFailure {
case x => println(s"FAIL: $x")
}
With monad transformers, failure scenario with
exception
FAIL: $line86.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw
$HotWaterException: Ouch spilled that water!
coffeeFutT:
cats.data.OptionT[scala.concurrent.Future,Coffee] =
OptionT(scala.concurrent.impl.Promise
$DefaultPromise@20e4013)
With monad transformers, failure scenario with
exception
flatMap
• Use monad transformers to short circuit your monads
What did we learn?
• Instead of unwrapping layers of monads, monad
transformers results in a new monad to flatMap with
• Reduce layers of x.map( y => y.map ( ... )) to just
x.map ( y => ...))
x.map ( y => y.map ( ... ) ) map
OptionT
What’s next?
• Many other types of monad transformers: ReaderT,
WriterT, EitherT, StateT
• Since monad transformers give you a monad as a
result-- you can stack them too!
Thank you
Connie Chen - @coni
Twilio
We’re hiring!
final case class OptionT[F[_], A](value: F[Option[A]]) {
def fold[B](default: => B)(f: A => B)(implicit F:
Functor[F]): F[B] =
F.map(value)(_.fold(default)(f))
def map[B](f: A => B)(implicit F: Functor[F]):
OptionT[F, B] =
OptionT(F.map(value)(_.map(f)))
def flatMapF[B](f: A => F[Option[B]])(implicit F:
Monad[F]): OptionT[F, B] =
OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]]
(None))(f)))
OptionT implementation
def liftF[F[_], A](fa: F[A])(implicit F:
Functor[F]): OptionT[F, A] = OptionT(F.map(fa)
(Some(_)))
OptionT implementation

More Related Content

Viewers also liked

Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jstakezoe
 
「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド
「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド
「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライドKeita Takizawa
 
Akka-chan's Survival Guide for the Streaming World
Akka-chan's Survival Guide for the Streaming WorldAkka-chan's Survival Guide for the Streaming World
Akka-chan's Survival Guide for the Streaming WorldKonrad Malawski
 
Deadly Code! (seriously) Blocking &amp; Hyper Context Switching Pattern
Deadly Code! (seriously) Blocking &amp; Hyper Context Switching PatternDeadly Code! (seriously) Blocking &amp; Hyper Context Switching Pattern
Deadly Code! (seriously) Blocking &amp; Hyper Context Switching Patternchibochibo
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lensNaoki Aoyama
 
アクセシビリティはじめました
アクセシビリティはじめましたアクセシビリティはじめました
アクセシビリティはじめましたYuichi Sugiyama
 
BCU30 - Webでできるマルチメディア表現
BCU30 - Webでできるマルチメディア表現BCU30 - Webでできるマルチメディア表現
BCU30 - Webでできるマルチメディア表現Leonardo Ken Orihara
 
Going bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data typesGoing bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data typesPawel Szulc
 
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigiReact Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigiYukiya Nakagawa
 
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのことDevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのことTerui Masashi
 
Akka Cluster and Auto-scaling
Akka Cluster and Auto-scalingAkka Cluster and Auto-scaling
Akka Cluster and Auto-scalingIkuo Matsumura
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/PrismNaoki Aoyama
 
AWSでアプリ開発するなら 知っておくべこと
AWSでアプリ開発するなら 知っておくべことAWSでアプリ開発するなら 知っておくべこと
AWSでアプリ開発するなら 知っておくべことKeisuke Nishitani
 
Big Data Analytics Tokyo
Big Data Analytics TokyoBig Data Analytics Tokyo
Big Data Analytics TokyoAdam Gibson
 
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)Eugene Yokota
 
バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri
バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuriバッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri
バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuriKazuki Negoro
 
あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)x1 ichi
 
Reactive integrations with Akka Streams
Reactive integrations with Akka StreamsReactive integrations with Akka Streams
Reactive integrations with Akka StreamsKonrad Malawski
 

Viewers also liked (20)

Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.js
 
「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド
「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド
「ハイレベルメンバーを共創させたら何が起きるか?実験」結果報告会 スライド
 
Akka-chan's Survival Guide for the Streaming World
Akka-chan's Survival Guide for the Streaming WorldAkka-chan's Survival Guide for the Streaming World
Akka-chan's Survival Guide for the Streaming World
 
Deadly Code! (seriously) Blocking &amp; Hyper Context Switching Pattern
Deadly Code! (seriously) Blocking &amp; Hyper Context Switching PatternDeadly Code! (seriously) Blocking &amp; Hyper Context Switching Pattern
Deadly Code! (seriously) Blocking &amp; Hyper Context Switching Pattern
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lens
 
アクセシビリティはじめました
アクセシビリティはじめましたアクセシビリティはじめました
アクセシビリティはじめました
 
BCU30 - Webでできるマルチメディア表現
BCU30 - Webでできるマルチメディア表現BCU30 - Webでできるマルチメディア表現
BCU30 - Webでできるマルチメディア表現
 
Scala Matsuri 2017
Scala Matsuri 2017Scala Matsuri 2017
Scala Matsuri 2017
 
Pratical eff
Pratical effPratical eff
Pratical eff
 
Going bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data typesGoing bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data types
 
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigiReact Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
 
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのことDevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
 
Akka Cluster and Auto-scaling
Akka Cluster and Auto-scalingAkka Cluster and Auto-scaling
Akka Cluster and Auto-scaling
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/Prism
 
AWSでアプリ開発するなら 知っておくべこと
AWSでアプリ開発するなら 知っておくべことAWSでアプリ開発するなら 知っておくべこと
AWSでアプリ開発するなら 知っておくべこと
 
Big Data Analytics Tokyo
Big Data Analytics TokyoBig Data Analytics Tokyo
Big Data Analytics Tokyo
 
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaMatsuri ver)
 
バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri
バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuriバッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri
バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri
 
あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)
 
Reactive integrations with Akka Streams
Reactive integrations with Akka StreamsReactive integrations with Akka Streams
Reactive integrations with Akka Streams
 

Similar to Reducing Boilerplate and Combining Effects: A Monad Transformer Example

Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Codemotion
 
For this homework, you will develop a class called VendingMachine th.pdf
For this homework, you will develop a class called VendingMachine th.pdfFor this homework, you will develop a class called VendingMachine th.pdf
For this homework, you will develop a class called VendingMachine th.pdfinfo309708
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScriptniklal
 
Getting property based testing to work after struggling for 3 years
Getting property based testing to work after struggling for 3 yearsGetting property based testing to work after struggling for 3 years
Getting property based testing to work after struggling for 3 yearsSaurabh Nanda
 
Coffeescript - take a sip of code
Coffeescript - take a sip of codeCoffeescript - take a sip of code
Coffeescript - take a sip of codeDimitris Tsironis
 
Php tour 2018 un autre regard sur la validation (1)
Php tour 2018   un autre regard sur la validation (1)Php tour 2018   un autre regard sur la validation (1)
Php tour 2018 un autre regard sur la validation (1)Quentin Pautrat
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreNicolas Carlo
 

Similar to Reducing Boilerplate and Combining Effects: A Monad Transformer Example (11)

Coffeescript slides
Coffeescript slidesCoffeescript slides
Coffeescript slides
 
test
testtest
test
 
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
 
Camel vs Spring EIP JAVA DSL
Camel vs Spring EIP JAVA DSLCamel vs Spring EIP JAVA DSL
Camel vs Spring EIP JAVA DSL
 
For this homework, you will develop a class called VendingMachine th.pdf
For this homework, you will develop a class called VendingMachine th.pdfFor this homework, you will develop a class called VendingMachine th.pdf
For this homework, you will develop a class called VendingMachine th.pdf
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 
Getting property based testing to work after struggling for 3 years
Getting property based testing to work after struggling for 3 yearsGetting property based testing to work after struggling for 3 years
Getting property based testing to work after struggling for 3 years
 
Coffeescript - take a sip of code
Coffeescript - take a sip of codeCoffeescript - take a sip of code
Coffeescript - take a sip of code
 
Php tour 2018 un autre regard sur la validation (1)
Php tour 2018   un autre regard sur la validation (1)Php tour 2018   un autre regard sur la validation (1)
Php tour 2018 un autre regard sur la validation (1)
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
 
Quick coffeescript
Quick coffeescriptQuick coffeescript
Quick coffeescript
 

Recently uploaded

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 

Recently uploaded (20)

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Odoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting ServiceOdoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting Service
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 

Reducing Boilerplate and Combining Effects: A Monad Transformer Example

  • 1. Reducing Boilerplate and Combining Effects: A Monad Transformer Example Scala Matsuri - Feb 25th, 2017 Connie Chen :
  • 2. Hello • @coni • Data Platform team @ Twilio • @ http://github.com/conniec
  • 3. • Monad transformers allow different monads to compose • Combine effects of monads to create a SUPER MONAD • Eg. Future[Option], Future[Either], Reader[Option] • In this example, we will use the Cats library... What are Monad transformers?
  • 4. Future[Either[A, B]] turns into EitherT[Future, A, B] Future[Option[A]] turns into OptionT[Future, A]
  • 5. import scala.concurrent.Future import cats.data.OptionT import cats.implicits._ import scala.concurrent.ExecutionContext.Implicits.glo bal case class Beans(fresh: Boolean = true) case class Grounds() class GroundBeansException(s: String) extends Exception(s: String) 1. Example: Making coffee! Step 1. Grind the beans
  • 6. def grindFreshBeans(beans: Beans, clumsy: Boolean = false): Future[Option[Grounds]] = { if (clumsy) { Future.failed(new GroundBeansException("We are bad at grinding")) } else if (beans.fresh) { Future.successful(Option(Grounds())) } else { Future.successful(None) } } 1. Example: Making coffee! Step 1. Grind the beans
  • 7. Step 1. Grind the beans Three different kind of results: • Value found • Value not found • Future failed Future 3 Example: Making coffee!
  • 8. Step 2. Boil hot water case class Kettle(filled: Boolean = true) case class Water() case class Coffee(delicious: Boolean) class HotWaterException(s: String) extends Exception(s: String) 2. def getHotWater(kettle: Kettle, clumsy: Boolean = false): Future[Option[Water]] = { if (clumsy) { Future.failed(new HotWaterException("Ouch spilled that water!")) } else if (kettle.filled) { Future.successful(Option(Water())) } else { Future.successful(None) } }
  • 9. Step 3. Combine water and coffee (it's a pourover) 3. ( ) def makingCoffee(grounds: Grounds, water: Water): Future[Coffee] = { println(s"Making coffee with... $grounds and $water") Future.successful(Coffee(delicious=true)) }
  • 10. val coffeeFut = for { } yield Option(result) coffeeFut.onSuccess { case Some(s) => println(s"SUCCESS: $s") case None => println("No coffee found?") } coffeeFut.onFailure { case x => println(s"FAIL: $x") } Without Monad transformers, success scenario beans <- grindFreshBeans(Beans(fresh=true)) hotWater <- getHotWater(Kettle(filled=true)) beansResult = beans.getOrElse(throw new Exception("Beans result errored. ")) waterResult = hotWater.getOrElse(throw new Exception("Water result errored. ")) result <- makingCoffee(beansResult, waterResult)
  • 11. Without Monad transformers, success scenario coffeeFut: scala.concurrent.Future[Option[Coffee]] = scala.concurrent.impl.Promise $DefaultPromise@7404ac2 scala> Making coffee with... Grounds() and Water() SUCCESS: Coffee(true)
  • 12. With Monad transformers, success scenario val coffeeFutMonadT = for { beans <- OptionT(grindFreshBeans(Beans(fresh=true))) hotWater <- OptionT(getHotWater(Kettle(filled=true))) result <- OptionT.liftF(makingCoffee(beans, hotWater)) } yield result coffeeFutMonadT.value.onSuccess { case Some(s) => println(s"SUCCESS: $s") case None => println("No coffee found?") } coffeeFutMonadT.value.onFailure { case x => println(s"FAIL: $x") }
  • 13. coffeeFutMonadT: cats.data.OptionT[scala.concurrent.Future, Coffee] = OptionT(scala.concurrent.impl.Promise $DefaultPromise@4a1c4b40) scala> Making coffee with... Grounds() and Water() SUCCESS: Coffee(true) With Monad transformers, success scenario
  • 14. OptionT `fromOption` gives you an OptionT from Option Internally, it is wrapping your option in a Future.successful() `liftF` gives you an OptionT from Future Internally, it is mapping on your Future and wrapping it in a Some() Helper functions on OptionT
  • 15. val coffeeFut = for { beans <- grindFreshBeans(Beans(fresh=false)) hotWater <- getHotWater(Kettle(filled=true)) beansResult = beans.getOrElse(throw new Exception("Beans result errored. ")) waterResult = hotWater.getOrElse(throw new Exception("Water result errored. ")) result <- makingCoffee(beansResult, waterResult) } yield Option(result) coffeeFut.onSuccess { case Some(s) => println(s"SUCCESS: $s") case None => println("No coffee found?") } coffeeFut.onFailure { case x => println(s"FAIL: $x") } Without Monad transformers, failure scenario
  • 16. Without Monad transformers, failure scenario coffeeFut: scala.concurrent.Future[Option[Coffee]] = scala.concurrent.impl.Promise $DefaultPromise@17ee3bd8 scala> FAIL: java.lang.Exception: Beans result errored.
  • 17. val coffeeFutT = for { beans <- OptionT(grindFreshBeans(Beans(fresh=false))) hotWater <- OptionT(getHotWater(Kettle(filled=true))) result <- OptionT.liftF(makingCoffee(beans, hotWater)) } yield result coffeeFutT.value.onSuccess { case Some(s) => println(s"SUCCESS: $s") case None => println("No coffee found?") } coffeeFutT.value.onFailure { case x => println(s"FAIL: $x") } With Monad transformers, failure scenario
  • 18. With Monad transformers, failure scenario coffeeFutT: cats.data.OptionT[scala.concurrent.Future ,Coffee] = OptionT(scala.concurrent.impl.Promise $DefaultPromise@4e115bbc) scala> No coffee found?
  • 19. val coffeeFutT = for { beans <- OptionT(grindFreshBeans(Beans(fresh=true))) hotWater <- OptionT(getHotWater(Kettle(filled=true), clumsy=true)) result <- OptionT.liftF(makingCoffee(beans, hotWater)) } yield s"$result" coffeeFutT.value.onSuccess { case Some(s) => println(s"SUCCESS: $s") case None => println("No coffee found?") } coffeeFutT.value.onFailure { case x => println(s"FAIL: $x") } With monad transformers, failure scenario with exception
  • 20. FAIL: $line86.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw $HotWaterException: Ouch spilled that water! coffeeFutT: cats.data.OptionT[scala.concurrent.Future,Coffee] = OptionT(scala.concurrent.impl.Promise $DefaultPromise@20e4013) With monad transformers, failure scenario with exception
  • 21. flatMap • Use monad transformers to short circuit your monads What did we learn? • Instead of unwrapping layers of monads, monad transformers results in a new monad to flatMap with • Reduce layers of x.map( y => y.map ( ... )) to just x.map ( y => ...)) x.map ( y => y.map ( ... ) ) map
  • 22. OptionT What’s next? • Many other types of monad transformers: ReaderT, WriterT, EitherT, StateT • Since monad transformers give you a monad as a result-- you can stack them too!
  • 23. Thank you Connie Chen - @coni Twilio We’re hiring!
  • 24. final case class OptionT[F[_], A](value: F[Option[A]]) { def fold[B](default: => B)(f: A => B)(implicit F: Functor[F]): F[B] = F.map(value)(_.fold(default)(f)) def map[B](f: A => B)(implicit F: Functor[F]): OptionT[F, B] = OptionT(F.map(value)(_.map(f))) def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): OptionT[F, B] = OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]] (None))(f))) OptionT implementation
  • 25. def liftF[F[_], A](fa: F[A])(implicit F: Functor[F]): OptionT[F, A] = OptionT(F.map(fa) (Some(_))) OptionT implementation