This document summarizes a presentation on monads explained to programmers. It discusses using monads like Try and Future in Scala to handle exceptions and asynchronous code in a functional way. It also discusses how monads allow separating technical concerns from business logic through composition. The presentation code examples demonstrate using for-comprehensions and flatMap with Try and Future to handle failures and combine asynchronous results in a declarative way.
2. FLATMAP ZAT SHIT
Les monades expliquées aux geeks
François Sarradin
Développeur λ
@fsarradin
27 au 29 mars
2013
3. François Sarradin
● Développeur λ
● http://kerflyn.wordpress.com/
@fsarradin
● "Je suis un bagger"
● http://www.brownbaglunch.fr/
@bbl_fr
4. Entity x = getEntity1()
Entity y = getEntity2()
Entity z = x.get() + y.get()
5. Entity x = getEntity1()
Entity y = getEntity2() Exception
Entity z = x.get() + y.get()
null
Asynchrone
6. if ()
(? ch
!= c at
if ( nu ...
? == ll
null ry
) Entity ) = getEntity1() lly
t ina
x
y . .. f
tr
Entity y = getEntity2()
nu ll)
(? != Entity z = x.get() + y.get()
try
if .. . ca
tch(
sy
z ed )
ad oni
nc
re hr
Th z .
h
Th nc
ro
re ed
ni ..
sy .
ad
..
7. Entity x = getEntity1()
Entity y = getEntity2()
Entity z = x.get() + y.get()
* Conserve le
code métier
12. Architecture
3: PROFIT! Web
JSON
2: ??? BankService
getAccount(b, n)
a:Account
AccountRepository
1: Get accounts
BankProxy BankProxy BankProxy
BGP La Postale Breizh Bank
13. def balanceByBank: String = { val balancesByBankJson:
Iterable[String] = for ((bankName, accountNumbers
<- ownerAccounts) yield { val balances:
List[Double] = for (accountNumber <-
accountNumbers.toList) yield
getAccount(bankName,
accountNumber
).balance Démonstration
s"""{"na
me":"$b
ankNam
Scala 2.10
e","b
alan
ce":
"${b
ala
nce
s.
su
m}
"}
"
" Code source sur Github
"
}
https://github.com/fsarradin/bankapp.git
27 au 29 mars
2013
14. Try[A]
val ok = Try { 1 }
ok: scala.util.Try[Int] = Success(1)
val ko = Try { throw new Exception("#1") }
ko: scala.util.Try[Nothing] = Failure(Exception: #1)
15. 1 Try[A] 1 for-expression
for { x <- ok } yield s"x = $x"
res1: scala.util.Try[String] = Success(x = 1)
for { x <- ko } yield s"x = $x"
res2: scala.util.Try[String] = Failure(Exception: #1)
16. 2 Try[A] 1 for-expression
val ok1: Try[Int] = Success(1)
val ok2: Try[Int] = Success(2)
val ko1: Try[Int] = Failure(new Exception("#1"))
val ko2: Try[Int] = Failure(new Exception("#2"))
for { x <- ok1; y <- ok2 } yield x + y
res1: scala.util.Try[Int] = Success(3)
for { x <- ko1; y <- ok2 } yield x + y
res2: scala.util.Try[String] = Failure(Exception: #1)
for { x <- ko1; y <- ko2 } yield x + y
res3: scala.util.Try[String] = Failure(Exception: #1)
17. def balanceByBank: String = { val balancesByBankJson:
Iterable[String] = for ((bankName, accountNumbers
<- ownerAccounts) yield { val balances:
List[Double] = for (accountNumber <-
accountNumbers.toList) yield
getAccount(bankName,
accountNumber
).balance Démonstration
s"""{"na
me":"$b
ankNam
Scala 2.10 : Try
e","b
alan
ce":
"${b
ala
nce
s.
su
m}
"}
"
" Code source sur Github
"
}
https://github.com/fsarradin/bankapp.git
27 au 29 mars
2013
19. Future[A] & for-expression
for { x <- fshort } yield s"x = $x"
res1: Future[String] ≈ Future("x = 1") // in fine
for { x <- fshort; y <- flong } yield x + y
res2: Future[Int] ≈ Future(3) // in fine
20. def balanceByBank: String = { val balancesByBankJson:
Iterable[String] = for ((bankName, accountNumbers
<- ownerAccounts) yield { val balances:
List[Double] = for (accountNumber <-
accountNumbers.toList) yield
getAccount(bankName,
accountNumber
).balance Démonstration
s"""{"na
me":"$b
ankNam
Scala 2.10 : Future
e","b
alan
ce":
"${b
ala
nce
s.
su
m}
"}
"
" Code source sur Github
"
}
https://github.com/fsarradin/bankapp.git
27 au 29 mars
2013
22. flatMap : opération monadique
for { m.map(x =>
x <- m x + 1
} )
yield x + 1
for { m1.flatMap(x =>
x <- m1 m2.map(y =>
y <- m2 x + y
} )
yield x + y )
23. def balanceByBank: String = { val balancesByBankJson:
Iterable[String] = for ((bankName, accountNumbers
<- ownerAccounts) yield { val balances:
List[Double] = for (accountNumber <-
accountNumbers.toList) yield
getAccount(bankName,
accountNumber
).balance Démonstration
s"""{"na
me":"$b
ankNam
Java 8 et les monades
e","b
alan
ce":
"${b
ala
nce
s.
su
m}
"}
"
" Code source sur Github
"
}
https://github.com/fsarradin/bankapp-java.git
27 au 29 mars
2013
24. Conclusion
● Code métier
○Peu de changement
● Système de type
○Aspect technique (déclaratif)
○Composition métier/technique => code
○Validation => compilateur