SlideShare a Scribd company logo
Final tagless and cats-mtl
Dublin 2019
Alexander Zaidel
Agenda
Examples
Examples
Examples
2
3
def validateUser(userToValidate: User): User = {
validateAge(userToValidate)
validatePassword(userToValidate)
}
4
private def validateAge(user: User): User =
if(user.age >= 18) user else throw new Exception("Age is not valid")
private def validatePassword(user: User): User =
if(user.password.length >= 6) user else throw new Exception("Password is not valid")
5
Use Option?
def validateUser(userToValidate: User): Option[User] = for {
_ <- validateAge(userToValidate)
_ <- validatePassword(userToValidate)
} yield userToValidate
6
private def validateAge(user: User): Option[User] =
if(user.age >= 18) Some(user) else None
private def validatePassword(user: User): Option[User] =
if(user.password.length >= 6) Some(user) else None
7
Use Try?
def validateUser(userToValidate: User): Try[User] = for {
_ <- validateAge(userToValidate)
_ <- validatePassword(userToValidate)
} yield userToValidate
8
private def validateAge(user: User): Try[User] =
if(user.age >= 18) Success(user) else Failure(new Exception("Age is not valid"))
private def validatePassword(user: User): Try[User] =
if(user.password.length >= 6) Success(user) else Failure(new Exception("Password is not
valid"))
9
Use Either?
def validateUser(userToValidate: User): Either[String, User] = for {
_ <- validateAge(userToValidate)
_ <- validatePassword(userToValidate)
} yield userToValidate
10
private def validateAge(user: User): Either[String, User] =
if(user.age >= 18) Right(user) else Left("Age is not valid")
private def validatePassword(user: User): Either[String, User] =
if(user.password.length >= 6) Right(user) else Left("Password is not valid")
11
def validateUser(userToValidate: User): F[User] = for {
_ <- validateAge(userToValidate)
_ <- validatePassword(userToValidate)
} yield userToValidate
12
private def validateAge(user: User): F[User] =
if(user.age >= 18) wrap[F](user) else error[F]
private def validatePassword(user: User): F[User] =
if(user.password.length >= 6) wrap[F](user) else error[F]
13
private def validateAge(user: User): F[User] =
if(user.age >= 18) pure[F](user) else raiseError[F]
private def validatePassword(user: User): F[User] =
if(user.password.length >= 6) pure[F](user) else raiseError[F]
14
MonadError
trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {
def raiseError[A](e: E): F[A]
def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A]
def pure[A](x: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B]
}
15
type ValidationError[F[_]] = MonadError[F, String]
class Validator[F[_]: ValidationError] {
val mE = implicitly[ValidationError[F]]
def validateUser(userToValidate: User): F[User] = for {
_ <- validateAge(userToValidate)
_ <- validatePassword(userToValidate)
} yield userToValidate
16
private def validateAge(user: User): F[User] =
if (user.age >= 18) mE.pure(user) else mE.raiseError("Age is not valid")
private def validatePassword(user: User): F[User] =
if (user.password.length >= 6) mE.pure(user) else mE.raiseError("Password is not valid")
}
17
private def validateAge(user: User): F[User] =
mE.ensure[User](mE.pure(user))("Age is not valid")(_.age >= 18)
private def validatePassword(user: User): F[User] =
mE.ensure(mE.pure(user))("Password is not valid")(u => u.password.length >= 6)
}
18
implicit val monadErrorOpt = new MonadError[Option, String] {
override def raiseError[A](e: String): Option[A] = None
override def handleErrorWith[A](fa: Option[A])(f: String => Option[A]): Option[A] =
fa match {
case r@Some(_) => r
case None => None
}
override def pure[A](x: A): Option[A] = Some(x)
19
override def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = for {
a <- fa
b <- f(a)
} yield b
@tailrec
override def tailRecM[A, B](a: A)(f: A => Option[Either[A, B]]): Option[B] = f(a) match {
case None => None
case Some(Left(a1)) => tailRecM(a1)(f)
case Some(Right(b)) => Some(b)
}
} 20
val validatorOpt = new Validator[Option]()
validatorOpt.validateUser(User("user1", 0, "strong"))
val validatorEither = new Validator[Either[String, ?]]()
validatorEither.validateUser(User("user2", 18, "weak"))
21
Learning scala
22
case class CreditCard(balance: Long)
sealed abstract class Item(valprice: Long)
case object ScalaCourse extends Item(100)
case object RedBook extends Item(200)
case object ScalaDaysTickets extends Item(1000)
23
def learnScala(creditCard: CreditCard): Unit = {
val (creditCard1, courseraScalaCourse) = buyCourseraSubscription(creditCard)
val (creditCard2, scalaRedBook) = buyRedBook(creditCard1)
val (creditCard3, scaladaysTickets) = buyScalaDaysTickets(creditCard1)
postTweet(List(courseraScalaCourse,
scalaRedBook,
scaladaysTickets), creditCard3)
}
24
case class State[S, A](run: S => (S, A)) {
def flatMap[B](f: A => State[S, B]): State[S, B] = State[S, B] { s0 =>
val (s1, a) = run(s0)
f(a).run(s1)
}
def map[B](f: A => B): State[S, B] = State[S, B] { s0 =>
val (s1, a) = run(s0)
s1 -> f(a)
}
}
25
def buyCourseraSubscription(creditCard: CreditCard): (CreditCard, Item) = {
creditCard.copy(balance = creditCard.balance - ScalaCourse.price) -> ScalaCourse
}
def buyRedBook(creditCard: CreditCard): (CreditCard, Item) = {
creditCard.copy(balance = creditCard.balance - RedBook.price) -> RedBook
}
def buyScalaDaysTickets(creditCard: CreditCard): (CreditCard, Item) = {
creditCard.copy(balance = creditCard.balance - ScalaDaysTickets.price) -> ScalaDaysTickets
}
26
def buyCourseraSubscription() = State[CreditCard, Item](creditCard =>
creditCard.copy(balance = creditCard.balance - ScalaCourse.price) -> ScalaCourse
)
def buyRedBook() = State[CreditCard, Item](creditCard =>
creditCard.copy(balance = creditCard.balance - RedBook.price) -> RedBook
)
def buyScalaDaysTickets() = State[CreditCard, Item](creditCard =>
creditCard.copy(balance = creditCard.balance - ScalaDaysTickets.price) -> ScalaDaysTickets
)
27
def learnScala(): State[CreditCard, Unit] = for {
scalaCourse <- buyCourseraSubscription()
redBook <- buyRedBook()
scalaDaysTickets <- buyScalaDaysTickets()
creditCard <- State.get
} yield postTweet(List(scalaCourse,
redBook,
scalaDaysTickets), creditCard)
28
def postTweet(items: List[Item], creditCard: CreditCard): Unit =
println(s"Check this out ${items.mkString(",")}. And I have ${creditCard.balance} left on my
account")
def postTweetIO(items: List[Item], creditCard: CreditCard): IO[Unit] =
IO(postTweet(items, creditCard))
29
def learnScalaIO(): StateT[IO, CreditCard, Unit] = for {
scalaCourse <- buyCourseraSubscription().mapK(evalToIO)
redBook <- buyRedBook().mapK(evalToIO)
scalaDaysTickets <- buyScalaDaysTickets().mapK(evalToIO)
creditCard <- StateT.get[IO, CreditCard]
_ <- StateT.liftF[IO, CreditCard, Unit](postTweetIO(List(scalaCourse,
redBook,
scalaDaysTickets), creditCard))
} yield ()
30
type State[S, A] = StateT[Eval, S, A]
val evalToIO = new arrow.FunctionK[Eval, IO] {
override def apply[A](fa: Eval[A]): IO[A] = IO(fa.value)
}
31
MonadState
trait MonadState[F[_], S] extends Serializable {
val monad: Monad[F]
def get: F[S]
def set(s: S): F[Unit]
def inspect[A](f: S => A): F[A]
def modify(f: S => S): F[Unit]
}
32
type CCState[F[_]] = MonadState[F, CreditCard]
class RoadToMonads[F[_] : CCState : Monad]() {
val ms = implicitly[CCState[F]]; val m = implicitly[Monad[F]]
def learnScala(): F[Unit] = for {
scalaCourse <- buyCourseraSubscription()
redBook <- buyRedBook()
scalaDaysTickets <- buyScalaDaysTickets()
creditCard <- ms.get
} yield postTweet(List(scalaCourse, redBook, scalaDaysTickets), creditCard)
33
private def postTweet(items: List[Item], creditCard: CreditCard): F[Unit] =
m.pure(println(s"Check this out ${items.mkString(",")}. And I have ${creditCard.balance} left on my
account"))
34
private def buyCourseraSubscription(): F[Item] =
ms.modify(cc => cc.copy(balance = cc.balance - ScalaCourse.price))
.map(_ => ScalaCourse)
private def buyRedBook(): F[Item] =
ms.modify(cc => cc.copy(balance = cc.balance - RedBook.price))
.map(_ => RedBook)
private def buyScalaDaysTickets(): F[Item] =
ms.modify(cc => cc.copy(balance = cc.balance - ScalaDaysTickets.price))
.map(_ => ScalaDaysTickets)
}
35
Wanna go crazy?
36
So why should I use MTL?
37
Q/A
38

More Related Content

What's hot

Open Selector
Open SelectorOpen Selector
Open Selector
jjdelc
 
Clean code
Clean codeClean code
Clean code
Lilit Mkrtchyan
 
Bacbkone js
Bacbkone jsBacbkone js
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
Louie Zhao
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency Injection
Anton Kril
 
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
nyccamp
 
Drupalcamp gent - Node access
Drupalcamp gent - Node accessDrupalcamp gent - Node access
Drupalcamp gent - Node access
Jasper Knops
 
Instant Dynamic Forms with #states
Instant Dynamic Forms with #statesInstant Dynamic Forms with #states
Instant Dynamic Forms with #states
Konstantin Käfer
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
Emanuele Quinto
 
Hacking Your Way To Better Security
Hacking Your Way To Better SecurityHacking Your Way To Better Security
Hacking Your Way To Better Security
Colin O'Dell
 
Daily notes
Daily notesDaily notes
Daily notes
meghendra168
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016
Colin O'Dell
 
course js day 3
course js day 3course js day 3
course js day 3
Georgyi Grigoryev
 
8 sql injection
8   sql injection8   sql injection
8 sql injection
drewz lin
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
Luiz Messias
 
Inception: Support Slides
Inception: Support SlidesInception: Support Slides
Inception: Support Slides
Nelson Brito
 
React.js: Beyond the Browser
React.js: Beyond the BrowserReact.js: Beyond the Browser
React.js: Beyond the Browser
garbles
 
Beautiful Development ブレイクスルー体験記
Beautiful Development ブレイクスルー体験記Beautiful Development ブレイクスルー体験記
Beautiful Development ブレイクスルー体験記
kentaro watanabe
 
Webit expo Standard Product
Webit expo Standard ProductWebit expo Standard Product
Webit expo Standard Product
Boji Ditcheva
 
The Ring programming language version 1.8 book - Part 12 of 202
The Ring programming language version 1.8 book - Part 12 of 202The Ring programming language version 1.8 book - Part 12 of 202
The Ring programming language version 1.8 book - Part 12 of 202
Mahmoud Samir Fayed
 

What's hot (20)

Open Selector
Open SelectorOpen Selector
Open Selector
 
Clean code
Clean codeClean code
Clean code
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency Injection
 
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
 
Drupalcamp gent - Node access
Drupalcamp gent - Node accessDrupalcamp gent - Node access
Drupalcamp gent - Node access
 
Instant Dynamic Forms with #states
Instant Dynamic Forms with #statesInstant Dynamic Forms with #states
Instant Dynamic Forms with #states
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
 
Hacking Your Way To Better Security
Hacking Your Way To Better SecurityHacking Your Way To Better Security
Hacking Your Way To Better Security
 
Daily notes
Daily notesDaily notes
Daily notes
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016
 
course js day 3
course js day 3course js day 3
course js day 3
 
8 sql injection
8   sql injection8   sql injection
8 sql injection
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 
Inception: Support Slides
Inception: Support SlidesInception: Support Slides
Inception: Support Slides
 
React.js: Beyond the Browser
React.js: Beyond the BrowserReact.js: Beyond the Browser
React.js: Beyond the Browser
 
Beautiful Development ブレイクスルー体験記
Beautiful Development ブレイクスルー体験記Beautiful Development ブレイクスルー体験記
Beautiful Development ブレイクスルー体験記
 
Webit expo Standard Product
Webit expo Standard ProductWebit expo Standard Product
Webit expo Standard Product
 
The Ring programming language version 1.8 book - Part 12 of 202
The Ring programming language version 1.8 book - Part 12 of 202The Ring programming language version 1.8 book - Part 12 of 202
The Ring programming language version 1.8 book - Part 12 of 202
 

Similar to Final tagless and cats mtl

Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
FIDO Alliance
 
CakePHP workshop
CakePHP workshopCakePHP workshop
CakePHP workshop
Walther Lalk
 
Symfony2. Form and Validation
Symfony2. Form and ValidationSymfony2. Form and Validation
Symfony2. Form and Validation
Vladimir Doroshenko
 
The Boy Scout Rule
The Boy Scout RuleThe Boy Scout Rule
The Boy Scout Rule
Alistair McKinnell
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
Daniel Knell
 
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Andrzej Jóźwiak
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
Marconi Moreto
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Tsuyoshi Yamamoto
 
Data::FormValidator Simplified
Data::FormValidator SimplifiedData::FormValidator Simplified
Data::FormValidator Simplified
Fred Moyer
 
Django (Web Konferencia 2009)
Django (Web Konferencia 2009)Django (Web Konferencia 2009)
Django (Web Konferencia 2009)
Szilveszter Farkas
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
GreeceJS
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
sergioafp
 
Scala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional ProgrammingScala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional Programming
Alex Fruzenshtein
 
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
tdc-globalcode
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
Rafael Winterhalter
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
Marcus Ramberg
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
Konstantin Kudryashov
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
eugenio pombi
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introduction
Iban Martinez
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
Yuya Takeyama
 

Similar to Final tagless and cats mtl (20)

Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
 
CakePHP workshop
CakePHP workshopCakePHP workshop
CakePHP workshop
 
Symfony2. Form and Validation
Symfony2. Form and ValidationSymfony2. Form and Validation
Symfony2. Form and Validation
 
The Boy Scout Rule
The Boy Scout RuleThe Boy Scout Rule
The Boy Scout Rule
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
Data::FormValidator Simplified
Data::FormValidator SimplifiedData::FormValidator Simplified
Data::FormValidator Simplified
 
Django (Web Konferencia 2009)
Django (Web Konferencia 2009)Django (Web Konferencia 2009)
Django (Web Konferencia 2009)
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Scala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional ProgrammingScala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional Programming
 
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introduction
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 

Recently uploaded

Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
Zilliz
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
Pixlogix Infotech
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
IndexBug
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 

Recently uploaded (20)

Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 

Final tagless and cats mtl

  • 1. Final tagless and cats-mtl Dublin 2019 Alexander Zaidel
  • 3. 3
  • 4. def validateUser(userToValidate: User): User = { validateAge(userToValidate) validatePassword(userToValidate) } 4
  • 5. private def validateAge(user: User): User = if(user.age >= 18) user else throw new Exception("Age is not valid") private def validatePassword(user: User): User = if(user.password.length >= 6) user else throw new Exception("Password is not valid") 5
  • 6. Use Option? def validateUser(userToValidate: User): Option[User] = for { _ <- validateAge(userToValidate) _ <- validatePassword(userToValidate) } yield userToValidate 6
  • 7. private def validateAge(user: User): Option[User] = if(user.age >= 18) Some(user) else None private def validatePassword(user: User): Option[User] = if(user.password.length >= 6) Some(user) else None 7
  • 8. Use Try? def validateUser(userToValidate: User): Try[User] = for { _ <- validateAge(userToValidate) _ <- validatePassword(userToValidate) } yield userToValidate 8
  • 9. private def validateAge(user: User): Try[User] = if(user.age >= 18) Success(user) else Failure(new Exception("Age is not valid")) private def validatePassword(user: User): Try[User] = if(user.password.length >= 6) Success(user) else Failure(new Exception("Password is not valid")) 9
  • 10. Use Either? def validateUser(userToValidate: User): Either[String, User] = for { _ <- validateAge(userToValidate) _ <- validatePassword(userToValidate) } yield userToValidate 10
  • 11. private def validateAge(user: User): Either[String, User] = if(user.age >= 18) Right(user) else Left("Age is not valid") private def validatePassword(user: User): Either[String, User] = if(user.password.length >= 6) Right(user) else Left("Password is not valid") 11
  • 12. def validateUser(userToValidate: User): F[User] = for { _ <- validateAge(userToValidate) _ <- validatePassword(userToValidate) } yield userToValidate 12
  • 13. private def validateAge(user: User): F[User] = if(user.age >= 18) wrap[F](user) else error[F] private def validatePassword(user: User): F[User] = if(user.password.length >= 6) wrap[F](user) else error[F] 13
  • 14. private def validateAge(user: User): F[User] = if(user.age >= 18) pure[F](user) else raiseError[F] private def validatePassword(user: User): F[User] = if(user.password.length >= 6) pure[F](user) else raiseError[F] 14
  • 15. MonadError trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] { def raiseError[A](e: E): F[A] def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A] def pure[A](x: A): F[A] def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B] } 15
  • 16. type ValidationError[F[_]] = MonadError[F, String] class Validator[F[_]: ValidationError] { val mE = implicitly[ValidationError[F]] def validateUser(userToValidate: User): F[User] = for { _ <- validateAge(userToValidate) _ <- validatePassword(userToValidate) } yield userToValidate 16
  • 17. private def validateAge(user: User): F[User] = if (user.age >= 18) mE.pure(user) else mE.raiseError("Age is not valid") private def validatePassword(user: User): F[User] = if (user.password.length >= 6) mE.pure(user) else mE.raiseError("Password is not valid") } 17
  • 18. private def validateAge(user: User): F[User] = mE.ensure[User](mE.pure(user))("Age is not valid")(_.age >= 18) private def validatePassword(user: User): F[User] = mE.ensure(mE.pure(user))("Password is not valid")(u => u.password.length >= 6) } 18
  • 19. implicit val monadErrorOpt = new MonadError[Option, String] { override def raiseError[A](e: String): Option[A] = None override def handleErrorWith[A](fa: Option[A])(f: String => Option[A]): Option[A] = fa match { case r@Some(_) => r case None => None } override def pure[A](x: A): Option[A] = Some(x) 19
  • 20. override def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = for { a <- fa b <- f(a) } yield b @tailrec override def tailRecM[A, B](a: A)(f: A => Option[Either[A, B]]): Option[B] = f(a) match { case None => None case Some(Left(a1)) => tailRecM(a1)(f) case Some(Right(b)) => Some(b) } } 20
  • 21. val validatorOpt = new Validator[Option]() validatorOpt.validateUser(User("user1", 0, "strong")) val validatorEither = new Validator[Either[String, ?]]() validatorEither.validateUser(User("user2", 18, "weak")) 21
  • 23. case class CreditCard(balance: Long) sealed abstract class Item(valprice: Long) case object ScalaCourse extends Item(100) case object RedBook extends Item(200) case object ScalaDaysTickets extends Item(1000) 23
  • 24. def learnScala(creditCard: CreditCard): Unit = { val (creditCard1, courseraScalaCourse) = buyCourseraSubscription(creditCard) val (creditCard2, scalaRedBook) = buyRedBook(creditCard1) val (creditCard3, scaladaysTickets) = buyScalaDaysTickets(creditCard1) postTweet(List(courseraScalaCourse, scalaRedBook, scaladaysTickets), creditCard3) } 24
  • 25. case class State[S, A](run: S => (S, A)) { def flatMap[B](f: A => State[S, B]): State[S, B] = State[S, B] { s0 => val (s1, a) = run(s0) f(a).run(s1) } def map[B](f: A => B): State[S, B] = State[S, B] { s0 => val (s1, a) = run(s0) s1 -> f(a) } } 25
  • 26. def buyCourseraSubscription(creditCard: CreditCard): (CreditCard, Item) = { creditCard.copy(balance = creditCard.balance - ScalaCourse.price) -> ScalaCourse } def buyRedBook(creditCard: CreditCard): (CreditCard, Item) = { creditCard.copy(balance = creditCard.balance - RedBook.price) -> RedBook } def buyScalaDaysTickets(creditCard: CreditCard): (CreditCard, Item) = { creditCard.copy(balance = creditCard.balance - ScalaDaysTickets.price) -> ScalaDaysTickets } 26
  • 27. def buyCourseraSubscription() = State[CreditCard, Item](creditCard => creditCard.copy(balance = creditCard.balance - ScalaCourse.price) -> ScalaCourse ) def buyRedBook() = State[CreditCard, Item](creditCard => creditCard.copy(balance = creditCard.balance - RedBook.price) -> RedBook ) def buyScalaDaysTickets() = State[CreditCard, Item](creditCard => creditCard.copy(balance = creditCard.balance - ScalaDaysTickets.price) -> ScalaDaysTickets ) 27
  • 28. def learnScala(): State[CreditCard, Unit] = for { scalaCourse <- buyCourseraSubscription() redBook <- buyRedBook() scalaDaysTickets <- buyScalaDaysTickets() creditCard <- State.get } yield postTweet(List(scalaCourse, redBook, scalaDaysTickets), creditCard) 28
  • 29. def postTweet(items: List[Item], creditCard: CreditCard): Unit = println(s"Check this out ${items.mkString(",")}. And I have ${creditCard.balance} left on my account") def postTweetIO(items: List[Item], creditCard: CreditCard): IO[Unit] = IO(postTweet(items, creditCard)) 29
  • 30. def learnScalaIO(): StateT[IO, CreditCard, Unit] = for { scalaCourse <- buyCourseraSubscription().mapK(evalToIO) redBook <- buyRedBook().mapK(evalToIO) scalaDaysTickets <- buyScalaDaysTickets().mapK(evalToIO) creditCard <- StateT.get[IO, CreditCard] _ <- StateT.liftF[IO, CreditCard, Unit](postTweetIO(List(scalaCourse, redBook, scalaDaysTickets), creditCard)) } yield () 30
  • 31. type State[S, A] = StateT[Eval, S, A] val evalToIO = new arrow.FunctionK[Eval, IO] { override def apply[A](fa: Eval[A]): IO[A] = IO(fa.value) } 31
  • 32. MonadState trait MonadState[F[_], S] extends Serializable { val monad: Monad[F] def get: F[S] def set(s: S): F[Unit] def inspect[A](f: S => A): F[A] def modify(f: S => S): F[Unit] } 32
  • 33. type CCState[F[_]] = MonadState[F, CreditCard] class RoadToMonads[F[_] : CCState : Monad]() { val ms = implicitly[CCState[F]]; val m = implicitly[Monad[F]] def learnScala(): F[Unit] = for { scalaCourse <- buyCourseraSubscription() redBook <- buyRedBook() scalaDaysTickets <- buyScalaDaysTickets() creditCard <- ms.get } yield postTweet(List(scalaCourse, redBook, scalaDaysTickets), creditCard) 33
  • 34. private def postTweet(items: List[Item], creditCard: CreditCard): F[Unit] = m.pure(println(s"Check this out ${items.mkString(",")}. And I have ${creditCard.balance} left on my account")) 34
  • 35. private def buyCourseraSubscription(): F[Item] = ms.modify(cc => cc.copy(balance = cc.balance - ScalaCourse.price)) .map(_ => ScalaCourse) private def buyRedBook(): F[Item] = ms.modify(cc => cc.copy(balance = cc.balance - RedBook.price)) .map(_ => RedBook) private def buyScalaDaysTickets(): F[Item] = ms.modify(cc => cc.copy(balance = cc.balance - ScalaDaysTickets.price)) .map(_ => ScalaDaysTickets) } 35
  • 37. So why should I use MTL? 37