SlideShare a Scribd company logo
1 of 168
Download to read offline
Monads
Asking the right question
WTF Monad?
In 30
minutes
WTF Monad?
“Hi”
“Sup?”
“I'm ready to write my first program. How
can I print some stuff to console?”
“Use IO Monad”
“What the *** is a monad?”
WTF Monad?
1. We understand code
1. We understand code
2. It is easier to talk about related ideas and
then abstract to something more general
1. We understand code
2. It is easier to talk about related ideas and
then abstract to something more general
3. Having abstract model created, we tend to
create metaphors
1. We understand code
2. It is easier to talk about related ideas and
then abstract to something more general
3. Having abstract model created, we tend to
create metaphors
4. Having all above we can formalize
Code & related ideas
Android, iOS, Windows Phone
Partner Lookup
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String =
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
println(partnerLookup(leonard))
println(partnerLookup(penny))
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
println(partnerLookup(leonard)) // output: "Cake Street 1"
println(partnerLookup(penny))
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
println(partnerLookup(leonard)) // output: "Cake Street 1"
println(partnerLookup(penny)) // output: "Academic St. 10"
“This app sucks!”
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val university = WorkPlace("University", "Academic St. 10")
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val university = WorkPlace("University", "Academic St. 10")
val rajesh = Geek("Rajesh", workPlace = university)
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val university = WorkPlace("University", "Academic St. 10")
val rajesh = Geek("Rajesh", workPlace = university)
println(partnerLookup(rajesh))
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val university = WorkPlace("University", "Academic St. 10")
val rajesh = Geek("Rajesh", workPlace = university)
println(partnerLookup(rajesh))
// java.lang.NullPointerException
// at wtf.examples.A1$.partnerLookUp(A1.scala:14)
// at ...
case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
case class WorkPlace(name: String, street: String)
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
val university = WorkPlace("University", "Academic St. 10")
val rajesh = Geek("Rajesh", workPlace = university)
println(partnerLookup(rajesh))
// java.lang.NullPointerException
// at wtf.examples.A1$.partnerLookUp(A1.scala:14)
// at ...
def partnerLookup(geek: Geek): String = {
}
def partnerLookup(geek: Geek): String = {
if(geek != null) {
}
def partnerLookup(geek: Geek): String = {
if(geek != null) {
if(geek.partner != null) {
}
def partnerLookup(geek: Geek): String = {
if(geek != null) {
if(geek.partner != null) {
if(geek.partner.workPlace != null) {
}
def partnerLookup(geek: Geek): String = {
if(geek != null) {
if(geek.partner != null) {
if(geek.partner.workPlace != null) {
if(geek.partner.workPlace.street != null) {
}
def partnerLookup(geek: Geek): String = {
if(geek != null) {
if(geek.partner != null) {
if(geek.partner.workPlace != null) {
if(geek.partner.workPlace.street != null) {
return geek.partner.workPlace.street
}
}
}
}
}
def partnerLookup(geek: Geek): String = {
if(geek != null) {
if(geek.partner != null) {
if(geek.partner.workPlace != null) {
if(geek.partner.workPlace.street != null) {
return geek.partner.workPlace.street
}
}
}
}
"not found"
}
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
val rajesh = Geek("Rajesh", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
println(partnerLookup(leonard)) // output: "Cake Street 1"
println(partnerLookup(penny)) // output: "Academic St. 10"
println(partnerLookup(rajesh)) // output: "not found"
def partnerLookup(geek: Geek): String = {
if(geek != null) {
if(geek.partner != null) {
if(geek.partner.workPlace != null) {
if(geek.partner.workPlace.street != null) {
return geek.partner.workPlace.street
}
}
}
}
"not found"
}
Call me: Maybe
sealed trait Maybe[+A]
sealed trait Maybe[+A]
case class Some[+A](value: A) extends Maybe[A]
sealed trait Maybe[+A]
case class Some[+A](value: A) extends Maybe[A]
case object None extends Maybe[Nothing]
sealed trait Maybe[+A]
case class Some[+A](value: A) extends Maybe[A]
case object None extends Maybe[Nothing]
object Maybe {
def apply[A](value: A) = Some(value)
}
sealed trait Maybe[+A] {
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
}
case object None extends Maybe[Nothing] {
}
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
}
case object None extends Maybe[Nothing] {
}
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
}
case object None extends Maybe[Nothing] {
}
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
}
case object None extends Maybe[Nothing] {
def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this
}
case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace])
case class WorkPlace(name: String, street: Maybe[String])
def partnerLookup(geek: Geek): String =
case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace])
case class WorkPlace(name: String, street: Maybe[String])
def partnerLookup(geek: Geek): String =
geek.partner
case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace])
case class WorkPlace(name: String, street: Maybe[String])
def partnerLookup(geek: Geek): String =
geek.partner.andThen(g => g.workPlace)
case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace])
case class WorkPlace(name: String, street: Maybe[String])
def partnerLookup(geek: Geek): String =
geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street)
case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace])
case class WorkPlace(name: String, street: Maybe[String])
def partnerLookup(geek: Geek): String =
geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
}
case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace])
case class WorkPlace(name: String, street: Maybe[String])
def partnerLookup(geek: Geek): String =
geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
val rajesh = Geek("Rajesh", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
println(partnerLookup(leonard))
println(partnerLookup(penny))
println(partnerLookup(rajesh))
val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1")
val university = WorkPlace("University", "Academic St. 10")
var penny = Geek("Penny", workPlace = cheeseCakeFactory)
var leonard = Geek("Leonard", workPlace = university)
val rajesh = Geek("Rajesh", workPlace = university)
penny = penny.copy(partner = leonard)
leonard = leonard.copy(partner = penny)
println(partnerLookup(leonard)) // output: "Cake Street 1"
println(partnerLookup(penny)) // output: "Academic St. 10"
println(partnerLookup(rajesh)) // output: "not found"
def partnerLookup(geek: Geek): String =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
def partnerLookup(geek: Geek): String =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
def partnerLookup(geek: Geek): String =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): String =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): String =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): String =
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] =
with a little bit of magic
For-comprehension
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] =
geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match {
case wtf.monads.Some(street) => street
case wtf.monads.None => "not found"
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
var leonard = Geek("Leonard", workPlace = university, partner = penny)
partnerLookup(leonard) // Some("Cake Street 1")
// how to print it?
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
}
case object None extends Maybe[Nothing] {
def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this
}
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
def within[B](f: A => B): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
}
case object None extends Maybe[Nothing] {
def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this
}
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
def within[B](f: A => B): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
}
case object None extends Maybe[Nothing] {
def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this
}
Reuse existing functionality like println
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
def within[B](f: A => B): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
def within[B](f: A => B): Maybe[B] = Maybe(f(value))
}
case object None extends Maybe[Nothing] {
def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this
}
sealed trait Maybe[+A] {
def andThen[B](f: A => Maybe[B]): Maybe[B]
def within[B](f: A => B): Maybe[B]
}
object Maybe {
def apply[A](value: A) = Some(value)
}
case class Some[+A](value: A) extends Maybe[A] {
def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value)
def within[B](f: A => B): Maybe[B] = Maybe(f(value))
}
case object None extends Maybe[Nothing] {
def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this
def within[B](f: Nothing => B): Maybe[B] = this
}
var leonard = Geek("Leonard", workPlace = university, partner = penny)
partnerLookup(leonard) // Some("Cake Street 1")
// how to print it?
var leonard = Geek("Leonard", workPlace = university, partner = penny)
partnerLookup(leonard)
var leonard = Geek("Leonard", workPlace = university, partner = penny)
partnerLookup(leonard).within(println) // output: "Cake Street 1"
Android, iOS, Windows Phone
Ship Inventory
case class Pirate(name: String, ships: Many[Ship])
case class Ship(name: String, hold: Hold)
case class Hold(barrel: Many[Barrel])
case class Barrel(amount: Int)
case class Pirate(name: String, ships: Many[Ship])
case class Ship(name: String, hold: Hold)
case class Hold(barrel: Many[Barrel])
case class Barrel(amount: Int)
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
case class Pirate(name: String, ships: Many[Ship])
case class Ship(name: String, hold: Hold)
case class Hold(barrel: Many[Barrel])
case class Barrel(amount: Int)
val blackPearl = Ship("Black Pearl", blackHold)
val whitePearl = Ship("White Pearl", whiteHold)
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
case class Pirate(name: String, ships: Many[Ship])
case class Ship(name: String, hold: Hold)
case class Hold(barrel: Many[Barrel])
case class Barrel(amount: Int)
val blackHold = Hold(Empty)
val whiteHold = Hold(Many(Barrel(20), Barrel(10)))
val blackPearl = Ship("Black Pearl", blackHold)
val whitePearl = Ship("White Pearl", whiteHold)
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
sealed trait Many[+A]
sealed trait Many[+A]
case class Const[+A](head: A, tail: Many[A]) extends Many[A]
sealed trait Many[+A]
case class Const[+A](head: A, tail: Many[A]) extends Many[A]
case object Empty extends Many[Nothing]
sealed trait Many[+A]
case class Const[+A](head: A, tail: Many[A]) extends Many[A]
case object Empty extends Many[Nothing]
object Many {
def apply[A](elements: A*): Many[A] = {
if(elements.length == 1) Const(elements(0), Empty)
else Const(elements(0), apply(elements.drop(1) : _*))
}
}
sealed trait Many[+A] {
def andThen[B](f: A => Many[B]): Many[B]
def within[B](f: A => B): Many[B]
}
case class Const[+A](head: A, tail: Many[A]) extends Many[A] {
def andThen[B](f: A => Many[B]): Many[B] = ...
def within[B](f: A => B): Many[B] = ...
}
case class Const[+A](head: A, tail: Many[A]) extends Many[A] {
def andThen[B](f: A => Many[B]): Many[B] = ...
def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f))
}
case class Const[+A](head: A, tail: Many[A]) extends Many[A] {
def andThen[B](f: A => Many[B]): Many[B] =
concat( f(head), tail.andThen(f) )
def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f))
}
case class Const[+A](head: A, tail: Many[A]) extends Many[A] {
def andThen[B](f: A => Many[B]): Many[B] =
concat( f(head), tail.andThen(f) )
private def concat[A](first: Many[A],
second: Many[A]): Many[A] = { … }
def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f))
}
case class Const[+A](head: A, tail: Many[A]) extends Many[A] {
def andThen[B](f: A => Many[B]): Many[B] =
concat( f(head), tail.andThen(f) )
private def concat[A](first: Many[A],
second: Many[A]): Many[A] = { … }
def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f))
}
case object Empty extends Many[Nothing] {
def andThen[B](f: Nothing => Many[B]): Many[B] = this
def within[B](f: Nothing => B): Many[B] = this
}
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
val blackPearl = Ship("Black Pearl", Hold(Empty))
val whitePearl = Ship("White Pearl",
Hold(Many(Barrel(20), Barrel(10))))
val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
jack.ships.andThen(ship => ship.hold.barrel)
.within(barrel => barrel.amount)
import Magic._
val amounts = for {
ship <- jack.ships
barrel <- ship.hold.barrel
} yield (barrel.amount)
println(amounts) // Const(20,Const(10,Empty))
● We've seen two wrapping classes.
● We've seen two wrapping classes.
● All have andThen method.
● We've seen two wrapping classes.
● All have andThen method.
● Each can take a function that can be called
on a value wrapped by the structure (which
can be empty or there can be multiple
instances of it).
Both were examples of a
Monad!
WTF Monad?
Monad is a container, a box.
Monad is a container, a box.
A box in which we can store
an object. Wrap it.
Monad is a container, a box.
A box in which we can store
an object, a value.
A box that has a common
interface, which allows us to
do one thing: connect
sequence of operations on the
content of the box.
Monad is a container, a box.
A box in which we can store
an object, a value.
A box that has a common
interface, which allows us to
do one thing: connect
sequence of operations on the
content of the box.
andThen means "do the next
things".
Monad is a container, a box.
A box in which we can store
an object, a value.
A box that has a common
interface, which allows us to
do one thing: connect
sequence of operations on the
content of the box.
andThen means "do the next
things".
But the way it is done depends
on a box.
Monad is a container, a box.
A box in which we can store
an object, a value.
A box that has a common
interface, which allows us to
do one thing: connect
sequence of operations on the
content of the box.
andThen means "do the next
things".
But the way it is done depends
on a box.
Monad is a container, a box.
A box in which we can store
an object, a value.
A box that has a common
interface, which allows us to
do one thing: connect
sequence of operations on the
content of the box.
andThen means "do the next
things".
But the way it is done depends
on a box.
Monad is a container, a box.
A box in which we can store
an object, a value.
A box that has a common
interface, which allows us to
do one thing: connect
sequence of operations on the
content of the box.
andThen means "do the next
things".
But the way it is done depends
on a box.
Monad is an abstract data type.
Monad is an abstract data type.
It has two operators: andThen and unit
Monad is an abstract data type.
It has two operators: andThen and unit
object Maybe {
def apply[A](value: A) = Some(value)
}
Monad is an abstract data type.
It has two operators: andThen and unit
Monad is an abstract data type.
It has two operators: andThen and unit
Monad is an abstract data type.
It has two operators: andThen and unit
bind (>>=) // formal name
Monad is an abstract data type.
It has two operators: andThen and unit
bind (>>=) // formal name
flatMap // in Scala
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
object Magic {
case class RichMaybe[A](m: Maybe[A]) {
def flatMap[B](f: A => Maybe[B]): Maybe[B] = m.andThen(f)
def map[B](f: A => B): Maybe[B] = m.within(f)
}
implicit def enrich[A](m: Maybe[A]) = RichMaybe(m)
}
def partnerLookup(geek: Geek): Maybe[String] = {
import Magic._
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
def partnerLookup(geek: Geek): Maybe[String] = {
for {
p <- geek.partner
wp <- p.workPlace
s <- wp.street
} yield (s)
}
Monad is an abstract data type.
It has two operators: bind and unit
Monad is an abstract data type.
It has two operators: bind and unit
Those operators must follow certain rules:
1. associativity
2. left identity
3. right identity
1. associativity
2. left identity
3. right identity
unit acts approximately as a
neutral element of bind
1. associativity
2. left identity
3. right identity
unit acts approximately as a
neutral element of bind
unit allows us to put value
into the box without
damaging it
1. associativity
2. left identity
3. right identity
unit acts approximately as a
neutral element of bind
unit(x).flatMap(f) == f(x)
m.flatMap(unit) == m
unit allows us to put value
into the box without
damaging it
1. associativity
2. left identity
3. right identity
“Binding two functions in
succession is the same as
binding one function that can
be determined from them”
1. associativity
2. left identity
3. right identity
m.flatMap{f(_)}.flatMap.{g(_)}
==
m.flatMap{f(_).flatMap.{g(_)}}
“Binding two functions in
succession is the same as
binding one function that can
be determined from them”
WTF Monad?
Paweł Szulc
Paweł Szulc
http://rabbitonweb.com
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
https://github.
com/rabbitonweb/monads_asking_the_right_
question
Thank you!
Images used
http://beforeitsnews.com/business/2014/02/career-tips-how-to-look-presentable-for-a-job-interview-2591264.html
http://phantommagician.deviantart.com/art/Cursed-Gold-183261313
http://carlosandgabbysbrooklyn.com/Burritos.html
http://channel9.msdn.com/Forums/Coffeehouse/442850-Sign-up-for-American-Programmer-C9park
https://www.pinterest.com/sandinarvaez/cute-graphics-and-patterns/
http://dsmconsulting.com.au/whats-in-the-box/
http://www.concordmonitor.com/home/4293575-95/cat-cats-videos-henri
https://www.pinterest.com/JoanneBest3/cats-in-boxes/
http://essaylab.org/
http://www.fanpop.com/clubs/pirates-of-the-caribbean/
http://library.sun.ac.za/SiteCollectionImages/search/Launch-Button.jpg

More Related Content

What's hot

Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. ExperienceMike Fogus
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidJordi Gerona
 
Python Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutPython Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutAudrey Roy
 
Clean code with google guava jee conf
Clean code with google guava jee confClean code with google guava jee conf
Clean code with google guava jee confIgor Anishchenko
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - StockholmJan Kronquist
 
Fun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming languageFun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming languagePawel Szulc
 
Understanding Prototypal Inheritance
Understanding Prototypal InheritanceUnderstanding Prototypal Inheritance
Understanding Prototypal InheritanceGuy Royse
 
JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJan Kronquist
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!Brendan Eich
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftGiordano Scalzo
 
Better Software: introduction to good code
Better Software: introduction to good codeBetter Software: introduction to good code
Better Software: introduction to good codeGiordano Scalzo
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
JavaScript Survival Guide
JavaScript Survival GuideJavaScript Survival Guide
JavaScript Survival GuideGiordano Scalzo
 
Code as data as code.
Code as data as code.Code as data as code.
Code as data as code.Mike Fogus
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to GroovyAnton Arhipov
 

What's hot (20)

Guava et Lombok au Normandy JUG
Guava et Lombok au Normandy JUGGuava et Lombok au Normandy JUG
Guava et Lombok au Normandy JUG
 
Guava et Lombok au Lorraine JUG
Guava et Lombok au Lorraine JUGGuava et Lombok au Lorraine JUG
Guava et Lombok au Lorraine JUG
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. Experience
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
Python Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutPython Tricks That You Can't Live Without
Python Tricks That You Can't Live Without
 
Go Java, Go!
Go Java, Go!Go Java, Go!
Go Java, Go!
 
Clean code with google guava jee conf
Clean code with google guava jee confClean code with google guava jee conf
Clean code with google guava jee conf
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - Stockholm
 
Fun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming languageFun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming language
 
Understanding Prototypal Inheritance
Understanding Prototypal InheritanceUnderstanding Prototypal Inheritance
Understanding Prototypal Inheritance
 
JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java Developers
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in Swift
 
Better Software: introduction to good code
Better Software: introduction to good codeBetter Software: introduction to good code
Better Software: introduction to good code
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
JavaScript Survival Guide
JavaScript Survival GuideJavaScript Survival Guide
JavaScript Survival Guide
 
JavaScript Patterns
JavaScript PatternsJavaScript Patterns
JavaScript Patterns
 
Code as data as code.
Code as data as code.Code as data as code.
Code as data as code.
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Groovy!
Groovy!Groovy!
Groovy!
 

Similar to Monads asking the right question

Criando app Android utilizando Kotlin
Criando app Android utilizando KotlinCriando app Android utilizando Kotlin
Criando app Android utilizando KotlinLuiz Henrique Santana
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme SwiftMovel
 
Wykorzystanie języka Kotlin do aplikacji na platformie Android
Wykorzystanie języka Kotlin do aplikacji na platformie AndroidWykorzystanie języka Kotlin do aplikacji na platformie Android
Wykorzystanie języka Kotlin do aplikacji na platformie Android3camp
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)William Narmontas
 
Getting acquainted with Lens
Getting acquainted with LensGetting acquainted with Lens
Getting acquainted with LensPawel Szulc
 
Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?Chang W. Doh
 
Introduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf TaiwanIntroduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf TaiwanJimin Hsieh
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Chang W. Doh
 
ScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyGautam Rege
 
What's in Groovy for Functional Programming
What's in Groovy for Functional ProgrammingWhat's in Groovy for Functional Programming
What's in Groovy for Functional ProgrammingNaresha K
 
Make GUI Apps with Shoes
Make GUI Apps with ShoesMake GUI Apps with Shoes
Make GUI Apps with ShoesBrian Hogan
 
GoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDDGoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDDBartłomiej Kiełbasa
 
Ruby and Rails by Example (GeekCamp edition)
Ruby and Rails by Example (GeekCamp edition)Ruby and Rails by Example (GeekCamp edition)
Ruby and Rails by Example (GeekCamp edition)bryanbibat
 
4Developers: Paweł Szulc- Real-World Gobbledygook
4Developers: Paweł Szulc- Real-World Gobbledygook 4Developers: Paweł Szulc- Real-World Gobbledygook
4Developers: Paweł Szulc- Real-World Gobbledygook PROIDEA
 
Reactive programming with RxSwift
Reactive programming with RxSwiftReactive programming with RxSwift
Reactive programming with RxSwiftScott Gardner
 
Ruby and Rails by example
Ruby and Rails by exampleRuby and Rails by example
Ruby and Rails by examplebryanbibat
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 

Similar to Monads asking the right question (20)

Criando app Android utilizando Kotlin
Criando app Android utilizando KotlinCriando app Android utilizando Kotlin
Criando app Android utilizando Kotlin
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
Wykorzystanie języka Kotlin do aplikacji na platformie Android
Wykorzystanie języka Kotlin do aplikacji na platformie AndroidWykorzystanie języka Kotlin do aplikacji na platformie Android
Wykorzystanie języka Kotlin do aplikacji na platformie Android
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)
 
Getting acquainted with Lens
Getting acquainted with LensGetting acquainted with Lens
Getting acquainted with Lens
 
Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?
 
Swift Study #7
Swift Study #7Swift Study #7
Swift Study #7
 
Introduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf TaiwanIntroduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf Taiwan
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요
 
ScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyScotRuby - Dark side of ruby
ScotRuby - Dark side of ruby
 
What's in Groovy for Functional Programming
What's in Groovy for Functional ProgrammingWhat's in Groovy for Functional Programming
What's in Groovy for Functional Programming
 
Make GUI Apps with Shoes
Make GUI Apps with ShoesMake GUI Apps with Shoes
Make GUI Apps with Shoes
 
GoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDDGoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDD
 
Ruby and Rails by Example (GeekCamp edition)
Ruby and Rails by Example (GeekCamp edition)Ruby and Rails by Example (GeekCamp edition)
Ruby and Rails by Example (GeekCamp edition)
 
4Developers: Paweł Szulc- Real-World Gobbledygook
4Developers: Paweł Szulc- Real-World Gobbledygook 4Developers: Paweł Szulc- Real-World Gobbledygook
4Developers: Paweł Szulc- Real-World Gobbledygook
 
Reactive programming with RxSwift
Reactive programming with RxSwiftReactive programming with RxSwift
Reactive programming with RxSwift
 
Scala vs Ruby
Scala vs RubyScala vs Ruby
Scala vs Ruby
 
Ruby and Rails by example
Ruby and Rails by exampleRuby and Rails by example
Ruby and Rails by example
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 

More from Pawel Szulc

Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Pawel Szulc
 
Painless Haskell
Painless HaskellPainless Haskell
Painless HaskellPawel Szulc
 
Trip with monads
Trip with monadsTrip with monads
Trip with monadsPawel Szulc
 
Trip with monads
Trip with monadsTrip with monads
Trip with monadsPawel Szulc
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineersPawel Szulc
 
RChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiRChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiPawel Szulc
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineersPawel Szulc
 
Understanding distributed calculi in Haskell
Understanding distributed calculi in HaskellUnderstanding distributed calculi in Haskell
Understanding distributed calculi in HaskellPawel Szulc
 
Software engineering the genesis
Software engineering  the genesisSoftware engineering  the genesis
Software engineering the genesisPawel Szulc
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs FreePawel Szulc
 
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
 
“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”Pawel Szulc
 
Writing your own RDD for fun and profit
Writing your own RDD for fun and profitWriting your own RDD for fun and profit
Writing your own RDD for fun and profitPawel Szulc
 
The cats toolbox a quick tour of some basic typeclasses
The cats toolbox  a quick tour of some basic typeclassesThe cats toolbox  a quick tour of some basic typeclasses
The cats toolbox a quick tour of some basic typeclassesPawel Szulc
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classesPawel Szulc
 
Apache spark workshop
Apache spark workshopApache spark workshop
Apache spark workshopPawel Szulc
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 minPawel Szulc
 
Apache spark when things go wrong
Apache spark   when things go wrongApache spark   when things go wrong
Apache spark when things go wrongPawel Szulc
 
Category theory is general abolute nonsens
Category theory is general abolute nonsensCategory theory is general abolute nonsens
Category theory is general abolute nonsensPawel Szulc
 

More from Pawel Szulc (20)

Impossibility
ImpossibilityImpossibility
Impossibility
 
Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)
 
Painless Haskell
Painless HaskellPainless Haskell
Painless Haskell
 
Trip with monads
Trip with monadsTrip with monads
Trip with monads
 
Trip with monads
Trip with monadsTrip with monads
Trip with monads
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineers
 
RChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiRChain - Understanding Distributed Calculi
RChain - Understanding Distributed Calculi
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineers
 
Understanding distributed calculi in Haskell
Understanding distributed calculi in HaskellUnderstanding distributed calculi in Haskell
Understanding distributed calculi in Haskell
 
Software engineering the genesis
Software engineering  the genesisSoftware engineering  the genesis
Software engineering the genesis
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs Free
 
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
 
“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”
 
Writing your own RDD for fun and profit
Writing your own RDD for fun and profitWriting your own RDD for fun and profit
Writing your own RDD for fun and profit
 
The cats toolbox a quick tour of some basic typeclasses
The cats toolbox  a quick tour of some basic typeclassesThe cats toolbox  a quick tour of some basic typeclasses
The cats toolbox a quick tour of some basic typeclasses
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
 
Apache spark workshop
Apache spark workshopApache spark workshop
Apache spark workshop
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
 
Apache spark when things go wrong
Apache spark   when things go wrongApache spark   when things go wrong
Apache spark when things go wrong
 
Category theory is general abolute nonsens
Category theory is general abolute nonsensCategory theory is general abolute nonsens
Category theory is general abolute nonsens
 

Recently uploaded

Contact Rya Baby for Call Girls New Delhi
Contact Rya Baby for Call Girls New DelhiContact Rya Baby for Call Girls New Delhi
Contact Rya Baby for Call Girls New Delhimiss dipika
 
Blepharitis inflammation of eyelid symptoms cause everything included along w...
Blepharitis inflammation of eyelid symptoms cause everything included along w...Blepharitis inflammation of eyelid symptoms cause everything included along w...
Blepharitis inflammation of eyelid symptoms cause everything included along w...Excelmac1
 
Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作
Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作
Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作ys8omjxb
 
VIP Kolkata Call Girl Kestopur 👉 8250192130 Available With Room
VIP Kolkata Call Girl Kestopur 👉 8250192130  Available With RoomVIP Kolkata Call Girl Kestopur 👉 8250192130  Available With Room
VIP Kolkata Call Girl Kestopur 👉 8250192130 Available With Roomdivyansh0kumar0
 
Font Performance - NYC WebPerf Meetup April '24
Font Performance - NYC WebPerf Meetup April '24Font Performance - NYC WebPerf Meetup April '24
Font Performance - NYC WebPerf Meetup April '24Paul Calvano
 
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)Christopher H Felton
 
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Dana Luther
 
Call Girls Near The Suryaa Hotel New Delhi 9873777170
Call Girls Near The Suryaa Hotel New Delhi 9873777170Call Girls Near The Suryaa Hotel New Delhi 9873777170
Call Girls Near The Suryaa Hotel New Delhi 9873777170Sonam Pathan
 
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130  Available With RoomVIP Kolkata Call Girl Alambazar 👉 8250192130  Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Roomdivyansh0kumar0
 
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书zdzoqco
 
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一Fs
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
Complet Documnetation for Smart Assistant Application for Disabled Person
Complet Documnetation   for Smart Assistant Application for Disabled PersonComplet Documnetation   for Smart Assistant Application for Disabled Person
Complet Documnetation for Smart Assistant Application for Disabled Personfurqan222004
 
办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一
办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一
办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一z xss
 
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012rehmti665
 
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一Fs
 
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With RoomVIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Roomishabajaj13
 

Recently uploaded (20)

Contact Rya Baby for Call Girls New Delhi
Contact Rya Baby for Call Girls New DelhiContact Rya Baby for Call Girls New Delhi
Contact Rya Baby for Call Girls New Delhi
 
Blepharitis inflammation of eyelid symptoms cause everything included along w...
Blepharitis inflammation of eyelid symptoms cause everything included along w...Blepharitis inflammation of eyelid symptoms cause everything included along w...
Blepharitis inflammation of eyelid symptoms cause everything included along w...
 
young call girls in Uttam Nagar🔝 9953056974 🔝 Delhi escort Service
young call girls in Uttam Nagar🔝 9953056974 🔝 Delhi escort Serviceyoung call girls in Uttam Nagar🔝 9953056974 🔝 Delhi escort Service
young call girls in Uttam Nagar🔝 9953056974 🔝 Delhi escort Service
 
Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Uttam Nagar Delhi 💯Call Us 🔝8264348440🔝
 
Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作
Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作
Potsdam FH学位证,波茨坦应用技术大学毕业证书1:1制作
 
VIP Kolkata Call Girl Kestopur 👉 8250192130 Available With Room
VIP Kolkata Call Girl Kestopur 👉 8250192130  Available With RoomVIP Kolkata Call Girl Kestopur 👉 8250192130  Available With Room
VIP Kolkata Call Girl Kestopur 👉 8250192130 Available With Room
 
Font Performance - NYC WebPerf Meetup April '24
Font Performance - NYC WebPerf Meetup April '24Font Performance - NYC WebPerf Meetup April '24
Font Performance - NYC WebPerf Meetup April '24
 
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
 
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
 
Call Girls Near The Suryaa Hotel New Delhi 9873777170
Call Girls Near The Suryaa Hotel New Delhi 9873777170Call Girls Near The Suryaa Hotel New Delhi 9873777170
Call Girls Near The Suryaa Hotel New Delhi 9873777170
 
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130  Available With RoomVIP Kolkata Call Girl Alambazar 👉 8250192130  Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
 
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
 
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
Complet Documnetation for Smart Assistant Application for Disabled Person
Complet Documnetation   for Smart Assistant Application for Disabled PersonComplet Documnetation   for Smart Assistant Application for Disabled Person
Complet Documnetation for Smart Assistant Application for Disabled Person
 
办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一
办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一
办理(UofR毕业证书)罗切斯特大学毕业证成绩单原版一比一
 
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
 
Hot Sexy call girls in Rk Puram 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in  Rk Puram 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in  Rk Puram 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Rk Puram 🔝 9953056974 🔝 Delhi escort Service
 
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
 
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With RoomVIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Room
 

Monads asking the right question

  • 3.
  • 4.
  • 5.
  • 6.
  • 11. “I'm ready to write my first program. How can I print some stuff to console?”
  • 13.
  • 14.
  • 15. “What the *** is a monad?”
  • 17.
  • 18.
  • 19.
  • 21. 1. We understand code 2. It is easier to talk about related ideas and then abstract to something more general
  • 22. 1. We understand code 2. It is easier to talk about related ideas and then abstract to something more general 3. Having abstract model created, we tend to create metaphors
  • 23. 1. We understand code 2. It is easier to talk about related ideas and then abstract to something more general 3. Having abstract model created, we tend to create metaphors 4. Having all above we can formalize
  • 24. Code & related ideas
  • 25.
  • 26. Android, iOS, Windows Phone Partner Lookup
  • 27. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace)
  • 28. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String)
  • 29. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String =
  • 30. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
  • 31. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10")
  • 32. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university)
  • 33. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny)
  • 34. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny) println(partnerLookup(leonard)) println(partnerLookup(penny))
  • 35. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny) println(partnerLookup(leonard)) // output: "Cake Street 1" println(partnerLookup(penny))
  • 36. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny) println(partnerLookup(leonard)) // output: "Cake Street 1" println(partnerLookup(penny)) // output: "Academic St. 10"
  • 37.
  • 38.
  • 39.
  • 41. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
  • 42.
  • 43. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street
  • 44. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val university = WorkPlace("University", "Academic St. 10")
  • 45. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val university = WorkPlace("University", "Academic St. 10") val rajesh = Geek("Rajesh", workPlace = university)
  • 46. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val university = WorkPlace("University", "Academic St. 10") val rajesh = Geek("Rajesh", workPlace = university) println(partnerLookup(rajesh))
  • 47. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val university = WorkPlace("University", "Academic St. 10") val rajesh = Geek("Rajesh", workPlace = university) println(partnerLookup(rajesh)) // java.lang.NullPointerException // at wtf.examples.A1$.partnerLookUp(A1.scala:14) // at ...
  • 48. case class Geek(name: String, partner: Geek = null, workPlace: WorkPlace) case class WorkPlace(name: String, street: String) def partnerLookup(geek: Geek): String = geek.partner.workPlace.street val university = WorkPlace("University", "Academic St. 10") val rajesh = Geek("Rajesh", workPlace = university) println(partnerLookup(rajesh)) // java.lang.NullPointerException // at wtf.examples.A1$.partnerLookUp(A1.scala:14) // at ...
  • 50. def partnerLookup(geek: Geek): String = { if(geek != null) { }
  • 51. def partnerLookup(geek: Geek): String = { if(geek != null) { if(geek.partner != null) { }
  • 52. def partnerLookup(geek: Geek): String = { if(geek != null) { if(geek.partner != null) { if(geek.partner.workPlace != null) { }
  • 53. def partnerLookup(geek: Geek): String = { if(geek != null) { if(geek.partner != null) { if(geek.partner.workPlace != null) { if(geek.partner.workPlace.street != null) { }
  • 54. def partnerLookup(geek: Geek): String = { if(geek != null) { if(geek.partner != null) { if(geek.partner.workPlace != null) { if(geek.partner.workPlace.street != null) { return geek.partner.workPlace.street } } } } }
  • 55. def partnerLookup(geek: Geek): String = { if(geek != null) { if(geek.partner != null) { if(geek.partner.workPlace != null) { if(geek.partner.workPlace.street != null) { return geek.partner.workPlace.street } } } } "not found" }
  • 56. val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) val rajesh = Geek("Rajesh", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny) println(partnerLookup(leonard)) // output: "Cake Street 1" println(partnerLookup(penny)) // output: "Academic St. 10" println(partnerLookup(rajesh)) // output: "not found"
  • 57. def partnerLookup(geek: Geek): String = { if(geek != null) { if(geek.partner != null) { if(geek.partner.workPlace != null) { if(geek.partner.workPlace.street != null) { return geek.partner.workPlace.street } } } } "not found" }
  • 60. sealed trait Maybe[+A] case class Some[+A](value: A) extends Maybe[A]
  • 61. sealed trait Maybe[+A] case class Some[+A](value: A) extends Maybe[A] case object None extends Maybe[Nothing]
  • 62. sealed trait Maybe[+A] case class Some[+A](value: A) extends Maybe[A] case object None extends Maybe[Nothing] object Maybe { def apply[A](value: A) = Some(value) }
  • 63. sealed trait Maybe[+A] { } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { } case object None extends Maybe[Nothing] { }
  • 64. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { } case object None extends Maybe[Nothing] { }
  • 65. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) } case object None extends Maybe[Nothing] { }
  • 66. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) } case object None extends Maybe[Nothing] { def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this }
  • 67. case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace]) case class WorkPlace(name: String, street: Maybe[String]) def partnerLookup(geek: Geek): String =
  • 68. case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace]) case class WorkPlace(name: String, street: Maybe[String]) def partnerLookup(geek: Geek): String = geek.partner
  • 69. case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace]) case class WorkPlace(name: String, street: Maybe[String]) def partnerLookup(geek: Geek): String = geek.partner.andThen(g => g.workPlace)
  • 70. case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace]) case class WorkPlace(name: String, street: Maybe[String]) def partnerLookup(geek: Geek): String = geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street)
  • 71. case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace]) case class WorkPlace(name: String, street: Maybe[String]) def partnerLookup(geek: Geek): String = geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street }
  • 72. case class Geek(name: String, partner: Maybe[Geek] = wtf.monads.None, workPlace: Maybe[WorkPlace]) case class WorkPlace(name: String, street: Maybe[String]) def partnerLookup(geek: Geek): String = geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" }
  • 73. val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) val rajesh = Geek("Rajesh", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny) println(partnerLookup(leonard)) println(partnerLookup(penny)) println(partnerLookup(rajesh))
  • 74. val cheeseCakeFactory = WorkPlace("Cheese Cake Factory", "Cake Street 1") val university = WorkPlace("University", "Academic St. 10") var penny = Geek("Penny", workPlace = cheeseCakeFactory) var leonard = Geek("Leonard", workPlace = university) val rajesh = Geek("Rajesh", workPlace = university) penny = penny.copy(partner = leonard) leonard = leonard.copy(partner = penny) println(partnerLookup(leonard)) // output: "Cake Street 1" println(partnerLookup(penny)) // output: "Academic St. 10" println(partnerLookup(rajesh)) // output: "not found"
  • 75. def partnerLookup(geek: Geek): String = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" }
  • 76. def partnerLookup(geek: Geek): String = geek.partner.workPlace.street def partnerLookup(geek: Geek): String = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" }
  • 77. def partnerLookup(geek: Geek): String = geek.partner.workPlace.street def partnerLookup(geek: Geek): String = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" }
  • 78. def partnerLookup(geek: Geek): String = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" }
  • 79. def partnerLookup(geek: Geek): String = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): String =
  • 80. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] =
  • 81. with a little bit of magic For-comprehension
  • 82. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { }
  • 83. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ }
  • 84. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(g => g.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 85. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 86. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 87. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 88. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 89. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 90. def partnerLookup(geek: Geek): Maybe[String] = geek.partner.andThen(p => p.workPlace).andThen(wp => wp.street) match { case wtf.monads.Some(street) => street case wtf.monads.None => "not found" } def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 91. var leonard = Geek("Leonard", workPlace = university, partner = penny) partnerLookup(leonard) // Some("Cake Street 1") // how to print it?
  • 92. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) } case object None extends Maybe[Nothing] { def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this }
  • 93. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] def within[B](f: A => B): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) } case object None extends Maybe[Nothing] { def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this }
  • 94. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] def within[B](f: A => B): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) } case object None extends Maybe[Nothing] { def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this } Reuse existing functionality like println
  • 95. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] def within[B](f: A => B): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) def within[B](f: A => B): Maybe[B] = Maybe(f(value)) } case object None extends Maybe[Nothing] { def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this }
  • 96. sealed trait Maybe[+A] { def andThen[B](f: A => Maybe[B]): Maybe[B] def within[B](f: A => B): Maybe[B] } object Maybe { def apply[A](value: A) = Some(value) } case class Some[+A](value: A) extends Maybe[A] { def andThen[B](f: A => Maybe[B]): Maybe[B] = f(value) def within[B](f: A => B): Maybe[B] = Maybe(f(value)) } case object None extends Maybe[Nothing] { def andThen[B](f: Nothing => Maybe[B]): Maybe[B] = this def within[B](f: Nothing => B): Maybe[B] = this }
  • 97. var leonard = Geek("Leonard", workPlace = university, partner = penny) partnerLookup(leonard) // Some("Cake Street 1") // how to print it?
  • 98. var leonard = Geek("Leonard", workPlace = university, partner = penny) partnerLookup(leonard)
  • 99. var leonard = Geek("Leonard", workPlace = university, partner = penny) partnerLookup(leonard).within(println) // output: "Cake Street 1"
  • 100.
  • 101.
  • 102. Android, iOS, Windows Phone Ship Inventory
  • 103. case class Pirate(name: String, ships: Many[Ship]) case class Ship(name: String, hold: Hold) case class Hold(barrel: Many[Barrel]) case class Barrel(amount: Int)
  • 104. case class Pirate(name: String, ships: Many[Ship]) case class Ship(name: String, hold: Hold) case class Hold(barrel: Many[Barrel]) case class Barrel(amount: Int) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
  • 105. case class Pirate(name: String, ships: Many[Ship]) case class Ship(name: String, hold: Hold) case class Hold(barrel: Many[Barrel]) case class Barrel(amount: Int) val blackPearl = Ship("Black Pearl", blackHold) val whitePearl = Ship("White Pearl", whiteHold) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
  • 106. case class Pirate(name: String, ships: Many[Ship]) case class Ship(name: String, hold: Hold) case class Hold(barrel: Many[Barrel]) case class Barrel(amount: Int) val blackHold = Hold(Empty) val whiteHold = Hold(Many(Barrel(20), Barrel(10))) val blackPearl = Ship("Black Pearl", blackHold) val whitePearl = Ship("White Pearl", whiteHold) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
  • 108. sealed trait Many[+A] case class Const[+A](head: A, tail: Many[A]) extends Many[A]
  • 109. sealed trait Many[+A] case class Const[+A](head: A, tail: Many[A]) extends Many[A] case object Empty extends Many[Nothing]
  • 110. sealed trait Many[+A] case class Const[+A](head: A, tail: Many[A]) extends Many[A] case object Empty extends Many[Nothing] object Many { def apply[A](elements: A*): Many[A] = { if(elements.length == 1) Const(elements(0), Empty) else Const(elements(0), apply(elements.drop(1) : _*)) } }
  • 111. sealed trait Many[+A] { def andThen[B](f: A => Many[B]): Many[B] def within[B](f: A => B): Many[B] }
  • 112. case class Const[+A](head: A, tail: Many[A]) extends Many[A] { def andThen[B](f: A => Many[B]): Many[B] = ... def within[B](f: A => B): Many[B] = ... }
  • 113. case class Const[+A](head: A, tail: Many[A]) extends Many[A] { def andThen[B](f: A => Many[B]): Many[B] = ... def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f)) }
  • 114. case class Const[+A](head: A, tail: Many[A]) extends Many[A] { def andThen[B](f: A => Many[B]): Many[B] = concat( f(head), tail.andThen(f) ) def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f)) }
  • 115. case class Const[+A](head: A, tail: Many[A]) extends Many[A] { def andThen[B](f: A => Many[B]): Many[B] = concat( f(head), tail.andThen(f) ) private def concat[A](first: Many[A], second: Many[A]): Many[A] = { … } def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f)) }
  • 116. case class Const[+A](head: A, tail: Many[A]) extends Many[A] { def andThen[B](f: A => Many[B]): Many[B] = concat( f(head), tail.andThen(f) ) private def concat[A](first: Many[A], second: Many[A]): Many[A] = { … } def within[B](f: A => B): Many[B] = Const(f(head), tail.within(f)) } case object Empty extends Many[Nothing] { def andThen[B](f: Nothing => Many[B]): Many[B] = this def within[B](f: Nothing => B): Many[B] = this }
  • 117. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl))
  • 118. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount)
  • 119. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount)
  • 120. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount)
  • 121. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount)
  • 122. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount)
  • 123. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount)
  • 124. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount)
  • 125. val blackPearl = Ship("Black Pearl", Hold(Empty)) val whitePearl = Ship("White Pearl", Hold(Many(Barrel(20), Barrel(10)))) val jack = Pirate("Captain Jack Sparrow", Many(blackPearl, whitePearl)) jack.ships.andThen(ship => ship.hold.barrel) .within(barrel => barrel.amount) import Magic._ val amounts = for { ship <- jack.ships barrel <- ship.hold.barrel } yield (barrel.amount) println(amounts) // Const(20,Const(10,Empty))
  • 126.
  • 127. ● We've seen two wrapping classes.
  • 128. ● We've seen two wrapping classes. ● All have andThen method.
  • 129. ● We've seen two wrapping classes. ● All have andThen method. ● Each can take a function that can be called on a value wrapped by the structure (which can be empty or there can be multiple instances of it).
  • 130. Both were examples of a Monad!
  • 132. Monad is a container, a box.
  • 133. Monad is a container, a box. A box in which we can store an object. Wrap it.
  • 134. Monad is a container, a box. A box in which we can store an object, a value. A box that has a common interface, which allows us to do one thing: connect sequence of operations on the content of the box.
  • 135. Monad is a container, a box. A box in which we can store an object, a value. A box that has a common interface, which allows us to do one thing: connect sequence of operations on the content of the box. andThen means "do the next things".
  • 136. Monad is a container, a box. A box in which we can store an object, a value. A box that has a common interface, which allows us to do one thing: connect sequence of operations on the content of the box. andThen means "do the next things". But the way it is done depends on a box.
  • 137. Monad is a container, a box. A box in which we can store an object, a value. A box that has a common interface, which allows us to do one thing: connect sequence of operations on the content of the box. andThen means "do the next things". But the way it is done depends on a box.
  • 138. Monad is a container, a box. A box in which we can store an object, a value. A box that has a common interface, which allows us to do one thing: connect sequence of operations on the content of the box. andThen means "do the next things". But the way it is done depends on a box.
  • 139. Monad is a container, a box. A box in which we can store an object, a value. A box that has a common interface, which allows us to do one thing: connect sequence of operations on the content of the box. andThen means "do the next things". But the way it is done depends on a box.
  • 140.
  • 141. Monad is an abstract data type.
  • 142. Monad is an abstract data type. It has two operators: andThen and unit
  • 143. Monad is an abstract data type. It has two operators: andThen and unit object Maybe { def apply[A](value: A) = Some(value) }
  • 144. Monad is an abstract data type. It has two operators: andThen and unit
  • 145. Monad is an abstract data type. It has two operators: andThen and unit
  • 146. Monad is an abstract data type. It has two operators: andThen and unit bind (>>=) // formal name
  • 147. Monad is an abstract data type. It has two operators: andThen and unit bind (>>=) // formal name flatMap // in Scala
  • 148. def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 149. def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 150. object Magic { case class RichMaybe[A](m: Maybe[A]) { def flatMap[B](f: A => Maybe[B]): Maybe[B] = m.andThen(f) def map[B](f: A => B): Maybe[B] = m.within(f) } implicit def enrich[A](m: Maybe[A]) = RichMaybe(m) }
  • 151. def partnerLookup(geek: Geek): Maybe[String] = { import Magic._ for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 152. def partnerLookup(geek: Geek): Maybe[String] = { for { p <- geek.partner wp <- p.workPlace s <- wp.street } yield (s) }
  • 153. Monad is an abstract data type. It has two operators: bind and unit
  • 154. Monad is an abstract data type. It has two operators: bind and unit Those operators must follow certain rules: 1. associativity 2. left identity 3. right identity
  • 155. 1. associativity 2. left identity 3. right identity unit acts approximately as a neutral element of bind
  • 156. 1. associativity 2. left identity 3. right identity unit acts approximately as a neutral element of bind unit allows us to put value into the box without damaging it
  • 157. 1. associativity 2. left identity 3. right identity unit acts approximately as a neutral element of bind unit(x).flatMap(f) == f(x) m.flatMap(unit) == m unit allows us to put value into the box without damaging it
  • 158. 1. associativity 2. left identity 3. right identity “Binding two functions in succession is the same as binding one function that can be determined from them”
  • 159. 1. associativity 2. left identity 3. right identity m.flatMap{f(_)}.flatMap.{g(_)} == m.flatMap{f(_).flatMap.{g(_)}} “Binding two functions in succession is the same as binding one function that can be determined from them”