Unblocking The Main Thread Solving ANRs and Frozen Frames
Grokking Monads in Scala
1. Grokking Monads in Scala St. Louis Lambda Lounge August 5, 2010 Tim Dalton Senior Software Engineer Object Computing Inc.
2. Monads Are… Just a monoid in the category of endofunctors. Like “duh”!
3.
4.
5.
6. Scala "For comprehensions" for (i <- 1 to 5) yield i scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5) for (i <- 1 to 5 if i % 2 == 0) yield i scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4) for (i <-1 to 5 if i % 2 == 0) { print (i + " " ) } 2 4 for (i <-1 to 5 if i % 2 == 0; j <- 1 to 5 if j % 2 != 0) yield ( i * j ) scala.collection.immutable.IndexedSeq[Int] = Vector(2, 6, 10, 4, 12, 20) for (i <-1 to 5 if i % 2 == 0; j <- 1 to 5 if j % 2 != 0; k <- 1 to 5) yield ( i * j / k ) scala.collection.immutable.IndexedSeq[Int] = Vector(2, 1, 0, 0, 0, 6, 3, 2, 1, 1, 10, 5, 3, 2, 2, 4, 2, 1, 1, 0, 12, 6, 4, 3, 2, 20, 10, 6, 5, 4)
7. De-sugarized For comprehensions (1 to 5).map(identity) scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5) (1 to 5).filter{_ % 2 == 0}.map(identity) scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4) (1 to 5).filter{_ % 2 == 0}.foreach { i => print (i + " " ) } 2 4 (1 to 5).filter{_ % 2 == 0}.flatMap { i => (1 to 5).filter{_ % 2 != 0}.map{ j => i * j } } scala.collection.immutable.IndexedSeq[Int] = Vector(2, 6, 10, 4, 12, 20) (1 to 5).filter{_ % 2 == 0}.flatMap { i => (1 to 5).filter{_ % 2 != 0}.flatMap{ j => (1 to 5).map{ k => i * j / k } } } scala.collection.immutable.IndexedSeq[Int] = Vector(2, 1, 0, 0, 0, 6, 3, 2, 1, 1, 10, 5, 3, 2, 2, 4, 2, 1, 1, 0, 12, 6, 4, 3, 2, 20, 10, 6, 5, 4)
8.
9. Simplest Monad – Identity case class Identity[A](value:A) { def map[B](f:(A) => B) = Identity(f(value)) def flatMap[B](f:(A) => Identity[B]) = f(value) }
10.
11. AST Evaluator – Identity object IdentityEvaluator extends EvaluatorTrait[Term, Identity[Int]] { def eval(term: Term) = term match { case Constant(x) => Identity(x) case Divide(a,b) => for (bp <- eval(b); ap <- eval(a)) yield (ap/bp) } println(eval(Divide(Divide(Constant(1972),Constant(2)), Constant(23)))) Identity(42) println(eval(Divide(Constant(1),Constant(0)))) Exception in thread "main" java.lang.ArithmeticException: / by zero
23. Links James Iry – “Monads are Elephants” http://james-iry.blogspot.com/2007/09/monads-are-elephants-part-1.html http://james-iry.blogspot.com/2007/10/monads-are-elephants-part-2.html http://james-iry.blogspot.com/2007/10/monads-are-elephants-part-3.html Philip Wadler’s Monad Papers http://homepages.inf.ed.ac.uk/wadler/topics/monads.html Brian Beckman Monad Videos http://channel9.msdn.com/shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads/ http://channel9.msdn.com/shows/Going+Deep/Brian-Beckman-The-Zen-of-Expressing-State-The-State-Monad/
Notas do Editor
I personally find the spacesuit metaphor the most helpful
Return == unit
Return == unit
flatMap for Scala sequences and lists implement the List Monad
No unit method is implemented here. Oftentimes constructors act has units. There are some high-level functions that can operate over different types of monads that often need a unit function Identity pretty much put the “astronaut in another suit”
State in this case sums the constants (kind of contrived)
State in this case sums the constants (kind of contrived)
State in this case sums the constants (kind of contrived)