Introduction to Monads in Scala (2)

6,170 views

Published on

0 Comments
14 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,170
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
115
Comments
0
Likes
14
Embeds 0
No embeds

No notes for slide

Introduction to Monads in Scala (2)

  1. 1. Monads Part 2functional programming with scala
  2. 2. Read this
  3. 3. Download it…
  4. 4. Scala is..
  5. 5. Choose your…• DSL• Actors• OOP• Procedures• Functional
  6. 6. public class VersionFormatter { private final String comp; public VersionFormatter(String comp) { this.comp = comp; } public String generate(String app) { return ”{" + comp + " - " + app + “}"; }}VersionFormatter myCompFormat = new VersionFormatter("Co");System.out.println(myCompFormat.generate("App"));
  7. 7. case class VersionFormatter(val comp: String) { def generateFor(app: String): String = ”{" + comp + " - " + app + “}"}val myCompFormat = VersionFormatter("Co")println(myCompFormat generateFor "App")
  8. 8. def generate(comp: String, app: String) = ”{%s - %s}".format(comp, app)val myCompFormat = generate ("Co", _: String)println(myCompFormat("App"))
  9. 9. Examplesreturn output filterById map toJsonls | grep ^d
  10. 10. val service = { path("orders") { authenticate(httpBasic(realm = "admin area")) { user => get { cacheResults(LruCache(maxCapacity = 1000, timeToIdle =Some(30.minutes))) { encodeResponse(Deflate) { completeWith { // marshal custom object with in-scope // marshaller getOrdersFromDB } } } }~
  11. 11. var avg: Option[Float] = from(grades)(g => where(g.subjectId === mathId) compute(avg( g.scoreInPercentage)))
  12. 12. “For” but not for…val ns = List(10, 20)val qs = for (n <- ns) yield n * 2assert (qs == List(20, 40))
  13. 13. Map like forval ns = List(10, 20)val qs = ns map {n => n * 2}
  14. 14. For like mapfor (x <- expr) yield resultExpr =expr map {x => resultExpr} =expr flatMap {x => unit(resultExpr)}
  15. 15. for [each] n [in] ns [and each] o [in] os yield n * oval in1 = List(1, 2)val in2 = List (3, 4)val out = for (n <- in1; o <- in2) yield n + oassert (out == List (1+3, 1+4, 2+3, 2+4)) =val out2 = in1 flatMap {n => in2 map {o => n + o }}assert(out == out2)
  16. 16. Step by stepval out = ns flatMap {n => os map {o => n + o }}val qs = ns flatMap {n => List(n + 3, n + 4)}val qs = List(1 + 3, 1 + 4, 2 + 3, 2 + 4)
  17. 17. More of For…val out = for (n <- in1; o <- in2; p <- in3) yield n + o + pval qs = ns flatMap {n => os flatMap {o => {ps map {p => n + o + p}}}}
  18. 18. rule is recursiveFor (x1 <- expr1;...x <- expr) yield resultExpr =expr1 flatMap {x1 => for(...;x <- expr) yield resultExpr}
  19. 19. Imperative "For"Just loosing yield:val ns = List(1, 2)val os = List (3, 4)for (n <- ns; o <- os) println(n + o) =ns foreach {n => os foreach {o => println(n + o) }}
  20. 20. Foreach is imperative form of "for"class M[A] { def map[B](f: A=> B) : M[B] = ... def flatMap[B](f: A => M[B]) : M[B] = ... def foreach[B](f: A=> B) : Unit = { map(f) return () }}
  21. 21. Filteringval names = List ( “Mike”, “Raph”, “Don”, “Leo” )val eNames = for (eName <- names; if eName.contains ( ‘e’ )) yield eName + “ is a name contains e”assert(eNames == List( "Mike is a name contains e", "Leo is a name contains e"))
  22. 22. Filtering with mapval bNames = (names filter { eName => eName.contains(e) }) .map { eName => eName + " is a namecontains e"}
  23. 23. Basis 2Haskell Scalado var1<- expn1 for {var1 <- expn1; var2 <- expn2 var2 <- expn2; expn3 result <- expn3 } yield resultdo var1 <- expn1 for {var1 <- expn1; var2 <- expn2 var2 <- expn2; return expn3 } yield expn3do var1 <- expn1 >> expn2 for {_ <- expn1; return expn3 var1 <- expn2 } yield expn3
  24. 24. Setting the Law f(x) ≡ g(x)But no eq, ==, hashCode, refAll the laws I present implicitly assume thatthere are no side effects.
  25. 25. Breaking the lawMathematic example: a*1≡a a*b≡b*a (a * b) * c ≡ a * (b * c)
  26. 26. WTF - What The Functor?In Scala a functor is a class with a map methodand a few simple properties. class M[A] { def map[B](f: A => B):M[B] = ... }
  27. 27. First Functor Law: Identity def identity[A](x:A) = x identity(x) ≡ xSo heres our first functor law: for any functor m – F1. m map identity ≡ m // or equivalently * – F1b. m map {x => identity(x)} ≡ m // or equivalently – F1c. m map {x => x} ≡ m
  28. 28. Always must be true– F1d. for (x <- m) yield x ≡ m
  29. 29. Second Functor Law: Composition F2. m map g map f ≡ m map {x => f(g(x))}
  30. 30. Always must workval result1 = m map (f compose g)val temp = m map gval result2 = temp map fassert result1 == result2
  31. 31. For analogueF2b. for (y<- (for (x <-m) yield g(x)) yield f(y) ≡ for (x <- m) yield f(g(x))
  32. 32. Functors and MonadsAll Monads are Functorsclass M[A] { def map[B](f: A => B):M[B] = ... def flatMap[B](f: A=> M[B]): M[B] = ... def unit[A](x:A):M[A] = …}Scala way for unit Object apply().
  33. 33. The Functor/Monad Connection LawFM1. m map f ≡ m flatMap {x => unit(f(x))} Three concepts: unit, map, and flatMap.FM1a. for (x <- m) yield f(x) ≡ for (x <- m; y <-unit(f(x))) yield y
  34. 34. Flatten in detailsFL1. m flatMap f ≡ flatten(m map f) =1. flatten(m map identity) ≡ m flatMap identity // substitute identity for f2. FL1a. flatten(m) ≡ m flatMap identity // by F1
  35. 35. The First Monad Law: Identity1. M1. m flatMap unit ≡ m // or equivalently2. M1a. m flatMap {x => unit(x)} ≡ mWhere the connector law connected 3 concepts,this law focuses on the relationship between 2of them
  36. 36. Identity• m flatMap {x => unit(x)} ≡ m // M1a• m flatMap {x => unit(identity(x))}≡ m // identity• F1b. m map {x => identity(x)} ≡ m // by FM1• M1c. for (x <- m; y <- unit(x)) yield y ≡ m
  37. 37. The Second Monad Law: Unit• M2. unit(x) flatMap f ≡ f(x) // or equivalently• M2a. unit(x) flatMap {y => f(y)} ≡ f(x)• M2b. for (y <- unit(x); result <- f(y)) yield result ≡ f(x)Its in precisely this sense that its safe to saythat any monad is a type of container (but thatdoesnt mean a monad is a collection!).
  38. 38. Rephrasing• unit(x) map f ≡ unit(x) map f // no, really, it does!• unit(x) map f ≡ unit(x) flatMap {y => unit(f(y))} // by FM1• M2c. unit(x) map f ≡ unit(f(x)) // by M2a• M2d. for (y <- unit(x)) yield f(y) ≡ unit(f(x))
  39. 39. The Third Monad Law: Composition• M3. m flatMap g flatMap f ≡ m flatMap {x => g(x) flatMap f} // orequivalently• M3a. m flatMap {x => g(x)} flatMap {y => f(y)} ≡ m flatMap {x => g(x) flatMap {y => f(y) }}
  40. 40. Mind breaker• M3b.for (a <- m; b <- g(a); result <- f(b) ) yield result ≡for (a <- m; result <- for(b < g(a); temp <- f(b) ) yield temp )yield result
  41. 41. ?1. m map g map f ≡ m map g map f // is it?2. m map g map f ≡ m flatMap {x => unit(g(x))} flatMap {y => unit(f(y))} // by FM1, twice3. m map g map f ≡ m flatMap {x => unit(g(x)) flatMap {y => unit(f(y))}} // by M3a4. m map g map f ≡ m flatMap {x => unit(g(x)) map {y => f(y)}} // by FM1a5. m map g map f ≡ m flatMap {x => unit(f(g(x))} // by M2c6. F2. m map g map f ≡ m map {x => f(g(x))} // by FM1a
  42. 42. Monadic zerosNill for ListNone for Option
  43. 43. The First Zero Law: IdentityMZ1. mzero flatMap f ≡ mzero1. mzero map f ≡ mzero map f // identity2. mzero map f ≡ mzero flatMap {x => unit(f(x)) // by FM13. MZ1b. mzero map f ≡ mzero // by MZ1
  44. 44. Not enough zerounit(null) map {x => "Nope, not empty enoughto be a zero"} ≡unit("Nope, not empty enough to be a zero")
  45. 45. The Second Zero Law: M to Zero in Nothing FlatMZ2. m flatMap {x => mzero} ≡ mzeroAnything to nothing is nothing
  46. 46. What is +Type MethodInt +List :::Option orElse
  47. 47. The Third and Fourth Zero Laws: Plusclass M[A] { ... def plus(other:M[B >: A]): M[B] = ...}• MZ3. mzero plus m ≡ m• MZ4. m plus mzero ≡ m
  48. 48. Filtering Againclass M[A] { def map[B](f: A => B):M[B] = ... def flatMap[B](f: A=> M[B]): M[B] = ... def filter(p: A=> Boolean): M[A] = ...}
  49. 49. Filter lawFIL1. m filter p ≡ m flatMap {x => if(p(x)) unit(x) else mzero}
  50. 50. Filter results 1• m filter {x => true} ≡ m filter {x => true} // identity• m filter {x => true} ≡ m flatMap {x => if (true) unit(x) else mzero} // by FIL1• m filter {x => true} ≡ m flatMap {x => unit(x)} // by definition of if• FIL1a. m filter {x => true} ≡ m // by M1
  51. 51. Filter results 2• m filter {x => false} ≡ m filter {x => false} // identity• m filter {x => false} ≡ m flatMap {x => if (false) unit(x) else mzero} // by FIL1• m filter {x => false} ≡ m flatMap {x => mzero} // by definition of if• FIL1b. m filter {x => false} ≡ mzero // by MZ1
  52. 52. Side Effectsm map g map f ≡ m map {x => (f(g(x)) }
  53. 53. Basis 3 Scala HaskellFM1 m map f ≡ m flatMap {x => fmap f m ≡ m >>= x -> return (f x) unit(f(x))}M1 m flatMap unit ≡ m m >>= return ≡ mM2 unit(x) flatMap f ≡ f(x) (return x) >>= f ≡ f xM3 m flatMap g flatMap f ≡ m (m >>= f) >>= g ≡ m >>= (x -> f x >>= g) flatMap {x => g(x) flatMap f}MZ1 mzero flatMap f ≡ mzero mzero >>= f ≡ mzeroMZ2 m flatMap {x => mzero} ≡ mzero m >>= (x -> mzero) ≡ mzeroMZ3 mzero plus m ≡ m mzero mplus m ≡ mMZ4 m plus mzero ≡ m m mplus mzero ≡ mFIL1 m filter p ≡ m flatMap {x => mfilter p m ≡ m >>= (x -> if p x then if(p(x)) unit(x) else mzero} return x else mzero)

×