SlideShare a Scribd company logo
1 of 58
Download to read offline
Monadologie —
  professional help for
          type anxiety

              Christopher League
              12 July 2010
Monadologie —
github.com/league/scala-type-anxiety




                @chrisleague
          league@contrapunctus.net
1996
Principles of
Programming
Languages


January 1997 § Paris
“Java might be the vehicle    Principles of
 that will help us carry      Programming
 modern programming
 language innovations         Languages
 into industrial practice.”
              – me
                              January 1997 § Paris
Scala
Monadologie
   continuations
         monads
     existentials
        variance
           effects
Monadologie
   continuations – control flow
         monads – data flow
Continuations
Continuation-
Passing
Style
def plus [A] (x: Int, y: Int, k: Int=>A): A =
    k(x+y)

def times [A] (x: Int, y: Int, k: Int=>A): A =
    k(x*y)

def less [A] (x: Int, y: Int,
              kt: => A, kf: => A): A =
    if(x < y) kt else kf
def factorial [A] (n: Int, k: Int => A): A =
    less(n, 2, k(1),
         plus(n, -1, (m:Int) =>
              factorial(m, (f:Int) =>
                        times(n, f, k))))


scala>   factorial(5, println)
120
scala>   factorial(3, factorial(_, println))
720
scala>   val n = factorial(3, r => r)
n: Int   = 6
CPS
makes some programs simpler
class Regex
case class Literal(s: String)    extends       Regex
case class Concat(r1: Regex, r2: Regex)
                                 extends       Regex
case class Choice(r1: Regex, r2: Regex)
                                 extends       Regex
case class Star(r: Regex)        extends       Regex

Concat(Star(Literal("ab")), Literal("abc"))
// (ab*)abc matches abababc

Choice(Star(Literal("ab")),
       Concat(Literal("a"), Star(Literal("ba"))))
// (ab)*|a(ba)* matches abababa
def accept (regex: Regex, chars: Seq[Char],
            k: Seq[Char] => Boolean): Boolean =
  regex match {
    case Literal(expect) =>
      if(chars.take(expect.length).sameElements(expect))
        k(chars.drop(expect.length))
      else false
    case Concat(regex1, regex2) =>
      accept(regex1, chars, remaining =>
        accept(regex2, remaining, k))
    case Choice(regex1, regex2) =>
      accept(regex1, chars, k) || accept(regex2, chars, k)
    case Star(repeatable) =>
      k(chars) ||
      accept(repeatable, chars, remaining =>
        accept(regex, remaining, k))
  }
def accept (regex: Regex, chars: Seq[Char],
            k: Seq[Char] => Boolean): Boolean =
  ...

def complete (remaining: Seq[Char]): Boolean =
    remaining.length == 0

accept(regex1, "abababc", complete) // true
accept(regex2, "abababa", complete) // true
accept(regex1, "abababcd", complete) // false
Delimited
Continuations
via compiler plugin (2.8)
Delimited
Continuations
    shift & reset
def doSomething0 = reset {
  println("Ready?")
  val result = 1 + special * 3
  println(result)
}


        Punch a hole in your code.
        What type of value is expected in the hole?
        What happens after the hole?
        What is result type of the reset block?
def doSomething0 = reset {
  println("Ready?")
  val result = 1 + special * 3
  println(result)
}


        Think of the rest of the computation as
        a function with the hole as its parameter.
        Call it the continuation.
def doSomething1 = reset {
  println("Ready?")
  val result = 1 + special * 3
  println(result)
}

def special = shift {
  k: (Int => Unit) =>
    println(99)
    "Gotcha!"     shift captures the continuation and
}                 then determines its own future.
def doSomething1 = reset {
  println("Ready?")
  val result = 1 + special * 3
  println(result)
}

def special = shift {
  k: (Int => Unit) =>
    println(99)
    "Gotcha!"     shift doSomething1
                scala> captures the continuation and
}               Ready?determines its own future.
                  then
                   99
                   res0: java.lang.String = Gotcha!
def doSomething2 = reset {
  println("Ready?")
  val result = 1 + wacky * 3
  println(result)
}

def wacky = shift {
  k: (Int => Unit) =>
    k(2)
    println("Yo!")
    k(3)
}
def doSomething2 = reset {
  println("Ready?")
  val result = 1 + wacky * 3
  println(result)
}

def wacky = shift {
  k: (Int => Unit) =>
    k(2)
    println("Yo!")    scala> doSomething2
    k(3)              Ready?
}                     7
                       Yo!
                       10
Continuation
low-level control-flow primitive that
can implement:
                exceptions
                concurrency (actors)
                suspensions (lazy)
                …
def multi = reset {
  println("This function returns tentatively")
  println("but you can always ask for more.")
  produce(42)
  println("Didn't like that? Back again.")
  produce(99)
  println("Still not OK? I'm out of ideas!")
  None
}
def multi = reset {
  println("This function returns tentatively")
  println("but you can always ask for more.")
  produce(42)
  println("Didn't like that? Back again.")
          scala> multi
  produce(99) function returns tentatively
          This
  println("Still can alwaysI'm out more.
          but you not OK? ask for of ideas!")
  None    res0: Option[ReturnThunk[Int]] = Some(...)
}         scala> println(res0.get.value)
          42
          scala> res0.get.proceed
          Didn’t like that? Back again.
          res1: Option[ReturnThunk[Int]] = Some(...)
          scala> println(res1.get.value)
          99
          scala> res1.get.proceed
          Still not OK? I’m out of ideas!
          res2: Option[ReturnThunk[Int]] = None
def multi = reset {
  println("This function returns tentatively")
  println("but you can always ask for more.")
  produce(42)
  println("Didn't like that? Back again.")
  produce(99)
  println("Still not OK? I'm out of ideas!")
  None
}
case class ReturnThunk[A]
  (value: A,
   proceed: Unit => Option[ReturnThunk[A]])

def produce [A] (value: A):
    Unit @cps[Option[ReturnThunk[A]]] =
  shift {
    k: (Unit => Option[ReturnThunk[A]]) =>
      Some(ReturnThunk(value, k))
  }
def multi = reset {
  println("This function returns tentatively")
  println("but you can always ask for more.")
  produce(42)
  println("Didn't like that? Back again.")
  produce(99)
  println("Still not OK? I'm out of ideas!")
  None
}
def interact = reset {
  val first = ask("Please give me a number")
  val second = ask("Enter another number")
  printf("The sum of your numbers is: %dn",
         first + second)
}
def interact = reset {
  val first = ask("Please give me a number")
  val second = ask("Enter another number")
  printf("The sum of your numbers is: %dn",
         first + second)
}
    scala> interact
    Please give me a number
    respond with: submit(0x28d092b7, ...)
    scala> submit(0x28d092b7, 14)
    Enter another number
    respond with: submit(0x1ddb017b, ...)
    scala> submit(0x1ddb017b, 28)
    The sum of your numbers is: 42
type UUID = Int
def uuidGen: UUID = Random.nextInt
type Data = Int
val sessions = new HashMap[UUID, Data=>Unit]

def ask(prompt: String): Data @cps[Unit] = shift {
    k: (Data => Unit) => {
      val id = uuidGen
      printf("%snrespond with: submit(0x%x, ...)n",
             prompt, id)
      sessions += id -> k
    }
}

def submit(id: UUID, data: Data) = sessions(id)(data)

def interact = reset {
  val first = ask("Please give me a number")
  val second = ask("Enter another number")
  printf("The sum of your numbers is: %dn",
         first + second)
}
HARMFUL
def harmful = reset {
    var i = 0
    println("Hello world!")
    label("loop")
    println(i)
    i = i + 1
    if(i < 20) goto("loop")
    println("Done.")
}
def harmful = reset {
    var i = 0
    println("Hello world!")   Hello world!
    label("loop")             0
    println(i)                1
    i = i + 1                 2
                              .
    if(i < 20) goto("loop")   .
    println("Done.")          .
}                             18
                              19
                              Done.
def harmful = reset {
    var i = 0
    println("Hello world!")
    label("loop")
    println(i)
    i = i + 1
    if(i < 20) goto("loop")
    println("Done.")
}
val labelMap = new HashMap[String, Unit=>Unit]

def label(name:String) =
  shift { k:(Unit=>Unit) =>
    labelMap += name -> k
    k()
  }
def goto(name:String) =
  shift { k:(Unit=>Unit) => labelMap(name)() }
def harmful = reset {
    var i = 0
    println("Hello world!")
    label("loop")
    println(i)
    i = i + 1
    if(i < 20) goto("loop")
    println("Done.")
}
Monads
the leading design pattern
for functional programming
A type constructor M is a monad
if it supports these operations:
 def unit[A] (x: A): M[A]

 def flatMap[A,B] (m: M[A]) (f: A => M[B]): M[B]

 def map[A,B] (m: M[A]) (f: A => B): M[B] =
   flatMap(m){ x => unit(f(x)) }

 def andThen[A,B] (ma: M[A]) (mb: M[B]): M[B] =
   flatMap(ma){ x => mb }
Option is a monad.
def unit[A] (x: A): Option[A] = Some(x)

def flatMap[A,B](m:Option[A])(f:A =>Option[B]):
    Option[B] =
  m match {
    case None => None
    case Some(x) => f(x)
  }
List is a monad.
def unit[A] (x: A): List[A] = List(x)

def flatMap[A,B](m:List[A])(f:A =>List[B]): List[B] =
  m match {
    case Nil => Nil
    case x::xs => f(x) ::: flatMap(xs)(f)
  }
For comprehension: convenient syntax for monadic structures.
            for(i    <- 1 to   4;
                j    <- 1 to   i;
                k    <- 1 to   j)
            yield    { i*j*k   }

Compiler translates it to:
         (1 to 4).flatMap { i =>
           (1 to i).flatMap { j =>
             (1 to j).map { k =>
               i*j*k }}}
Example: a series of operations, where each may fail.
 lookupVenue: String => Option[Venue]
 getLoggedInUser: SessionID => Option[User]
 reserveTable: (Venue, User) => Option[ConfNo]
Example: a series of operations, where each may fail.
 lookupVenue: String => Option[Venue]
 getLoggedInUser: SessionID => Option[User]
 reserveTable: (Venue, User) => Option[ConfNo]

 val user = getLoggedInUser(session)
 val confirm =
   if(!user.isDefined) { None }
   else lookupVenue(name) match {
     case None => None
     case Some(venue) => {
       val confno = reserveTable(venue, user.get)
       if(confno.isDefined)
         mailTo(confno.get, user.get)
       confno
     }
   }
Example: a series of operations, where each may fail.
 lookupVenue: String => Option[Venue]
 getLoggedInUser: SessionID => Option[User]
 reserveTable: (Venue, User) => Option[ConfNo]

 val user = getLoggedInUser(session)
 val confirm =
   if(!user.isDefined) { None }
   else lookupVenue(name) match {
     case None => None
     case Some(venue) => {
       val confno = reserveTable(venue, user.get)
       if(confno.isDefined)
         mailTo(confno.get, user.get)
       confno
     }
   }
Example: a series of operations, where each may fail.
 lookupVenue: String => Option[Venue]
 getLoggedInUser: SessionID => Option[User]
 reserveTable: (Venue, User) => Option[ConfNo]

 val confirm =
   for(venue <- lookupVenue(name);
       user <- getLoggedInUser(session);
       confno <- reserveTable(venue, user))
   yield {
     mailTo(confno, user)
     confno
   }
Example from Lift form validation:
  def addUser(): Box[UserInfo] =
    for {
      firstname <- S.param("firstname") ?~
                  "firstname parameter missing" ~> 400
      lastname <- S.param("lastname") ?~
                  "lastname parameter missing"
      email <- S.param("email") ?~
                  "email parameter missing"
    } yield {
      val u = User.create.firstName(firstname).
      lastName(lastname).email(email)

        S.param("password") foreach u.password.set

        u.saveMe
    }
Example: use monad to pass around state behind the scenes

 class Tree[A]
 case class Leaf[A](elem: A) extends Tree[A]
 case class Branch[A](left: Tree[A], right: Tree[A])
        extends Tree[A]

 inject(‘Q’,        )               =>


    f               a                    Q               c
        d                       b            f                       g

            e   c       h   g                    d   e       a   h
def inject[A] (root: Tree[A], cur: A): (Tree[A], A) =
    root match {
      case Leaf(old) => (Leaf(cur), old)
      case Branch(left, right) =>
        val (t1, last1) = inject(left, cur)
        val (t2, last2) = inject(right, last1)
        (Branch(t1,t2), last2)
    }
def inject[A] (root: Tree[A], cur: A): (Tree[A], A) =
    root match {
      case Leaf(old) => (Leaf(cur), old)
      case Branch(left, right) =>
        val (t1, last1) = inject(left, cur)
        val (t2, last2) = inject(right, last1)
        (Branch(t1,t2), last2)
    }
def injectST[A] (root: Tree[A]): ST[A, Tree[A]] =
    root match {
      case Leaf(old) =>
        for(cur <- init[A];
            u <- update[A](_ => old))
          yield Leaf(cur)
      case Branch(left, right) =>
        for(t1 <- injectST(left);
            t2 <- injectST(right))
          yield Branch(t1,t2)
    }
case class ST[S,A](exec: S => (S,A)) {
  def flatMap[B] (f: A => ST[S,B]): ST[S,B] =
    ST { s0 =>
      val (s1, a) = exec(s0)
      f(a).exec(s1)
      }

    def map[B] (f: A => B)
          (implicit unit: B => ST[S,B]) : ST[S,B] =
      flatMap { x => unit(f(x)) }
}

implicit def unitST[S,A] (x: A): ST[S,A] =
  ST { s0 => (s0, x) }

def init[S]: ST[S,S] =
  ST { s0 => (s0, s0) }

def update[S] (g: S => S): ST[S,Unit] =
  ST { s0 => (g(s0), ()) }
case class ST[S,A](exec: S => (S,A)) {
  def flatMap[B] (f: scala> ST[S,B]): ST[S,B] =
                     A => drawTree(t1,"")
    ST { s0 =>       ______f
                     | _____d
      val (s1, a) = exec(s0)
                     |     _____e
      f(a).exec(s1) |         __c
      }              _____a
                             ________h
                                | __g
    def map[B] (f: A =>     B) __b
          (implicit unit: B => ST[S,B]) : ST[S,B] =
      flatMap { x => unit(f(x)) m }= injectST(t1)
                       scala> val
                       m: ST[Char,Tree[Char]] = ST(<function1>)
}
                          scala> val (_,t2) = m.exec('Q')
                          t2: Tree[Char] = ...
implicit def unitST[S,A] (x: A): ST[S,A] =
  ST { s0 => (s0, x) scala> drawTree(t2,"")
                     }
                     ______Q
def init[S]: ST[S,S] | _____f
                     =
                     |      _____d
  ST { s0 => (s0, s0)| }       __e
                     _____c
                         ________a
def update[S] (g: S => S): ST[S,Unit]
                            | __h
                                                =
  ST { s0 => (g(s0), ()) }  __g
Monadologie
github.com/league/scala-type-anxiety




                @chrisleague
          league@contrapunctus.net

More Related Content

What's hot

[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8Alonso Torres
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingSergey Shishkin
 
The Ring programming language version 1.3 book - Part 25 of 88
The Ring programming language version 1.3 book - Part 25 of 88The Ring programming language version 1.3 book - Part 25 of 88
The Ring programming language version 1.3 book - Part 25 of 88Mahmoud Samir Fayed
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceAlexey Raga
 
The Ring programming language version 1.7 book - Part 40 of 196
The Ring programming language version 1.7 book - Part 40 of 196The Ring programming language version 1.7 book - Part 40 of 196
The Ring programming language version 1.7 book - Part 40 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210Mahmoud Samir Fayed
 
深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscexjeffz
 
λ | Lenses
λ | Lensesλ | Lenses
λ | LensesOpen-IT
 
The Ring programming language version 1.5.2 book - Part 32 of 181
The Ring programming language version 1.5.2 book - Part 32 of 181The Ring programming language version 1.5.2 book - Part 32 of 181
The Ring programming language version 1.5.2 book - Part 32 of 181Mahmoud Samir Fayed
 
Tupple ware in scala
Tupple ware in scalaTupple ware in scala
Tupple ware in scalaVulcanMinds
 
The Ring programming language version 1.10 book - Part 43 of 212
The Ring programming language version 1.10 book - Part 43 of 212The Ring programming language version 1.10 book - Part 43 of 212
The Ring programming language version 1.10 book - Part 43 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84Mahmoud Samir Fayed
 
Introduction to idris
Introduction to idrisIntroduction to idris
Introduction to idrisConor Farrell
 
The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88Mahmoud Samir Fayed
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of AbstractionAlex Miller
 

What's hot (20)

[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
 
Struct examples
Struct examplesStruct examples
Struct examples
 
The Ring programming language version 1.3 book - Part 25 of 88
The Ring programming language version 1.3 book - Part 25 of 88The Ring programming language version 1.3 book - Part 25 of 88
The Ring programming language version 1.3 book - Part 25 of 88
 
Oh Composable World!
Oh Composable World!Oh Composable World!
Oh Composable World!
 
Scala taxonomy
Scala taxonomyScala taxonomy
Scala taxonomy
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritance
 
The Ring programming language version 1.7 book - Part 40 of 196
The Ring programming language version 1.7 book - Part 40 of 196The Ring programming language version 1.7 book - Part 40 of 196
The Ring programming language version 1.7 book - Part 40 of 196
 
The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210
 
深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscex
 
Error Handling in Scala
Error Handling in ScalaError Handling in Scala
Error Handling in Scala
 
λ | Lenses
λ | Lensesλ | Lenses
λ | Lenses
 
The Ring programming language version 1.5.2 book - Part 32 of 181
The Ring programming language version 1.5.2 book - Part 32 of 181The Ring programming language version 1.5.2 book - Part 32 of 181
The Ring programming language version 1.5.2 book - Part 32 of 181
 
Tupple ware in scala
Tupple ware in scalaTupple ware in scala
Tupple ware in scala
 
The Ring programming language version 1.10 book - Part 43 of 212
The Ring programming language version 1.10 book - Part 43 of 212The Ring programming language version 1.10 book - Part 43 of 212
The Ring programming language version 1.10 book - Part 43 of 212
 
The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84
 
Introduction to idris
Introduction to idrisIntroduction to idris
Introduction to idris
 
The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of Abstraction
 
Functional Scala 2020
Functional Scala 2020Functional Scala 2020
Functional Scala 2020
 

Similar to Here is how you could write this as a for comprehension:for { venue <- lookupVenue("The Dancing Ferret") user <- getLoggedInUser(sessionId) confNo <- reserveTable(venue, user)} yield confNoThis translates each operation to a flatMap, sequencing the computations so that if any operation returns None, the whole computation short-circuits without evaluating the remaining steps.So monads like Option allow modeling failure/exceptions in a composable way. Monad laws:Left identity: unit(x).flatMap(f) == f(x)Right identity: m.flatMap(unit) == m

Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patternsleague
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsEelco Visser
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Parametricity - #cljsyd - May, 2015
Parametricity - #cljsyd - May, 2015Parametricity - #cljsyd - May, 2015
Parametricity - #cljsyd - May, 2015Leonardo Borges
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2Hang Zhao
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksSeniorDevOnly
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For GoogleEleanor McHugh
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using ScalaSiarhiej Siemianchuk
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scalapramode_ce
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Baruch Sadogursky
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming iiPrashant Kalkar
 

Similar to Here is how you could write this as a for comprehension:for { venue <- lookupVenue("The Dancing Ferret") user <- getLoggedInUser(sessionId) confNo <- reserveTable(venue, user)} yield confNoThis translates each operation to a flatMap, sequencing the computations so that if any operation returns None, the whole computation short-circuits without evaluating the remaining steps.So monads like Option allow modeling failure/exceptions in a composable way. Monad laws:Left identity: unit(x).flatMap(f) == f(x)Right identity: m.flatMap(unit) == m (20)

Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Parametricity - #cljsyd - May, 2015
Parametricity - #cljsyd - May, 2015Parametricity - #cljsyd - May, 2015
Parametricity - #cljsyd - May, 2015
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For Google
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using Scala
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
 

More from league

On the Edge, 2013
On the Edge, 2013On the Edge, 2013
On the Edge, 2013league
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Languageleague
 
On the edge
On the edgeOn the edge
On the edgeleague
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systemsleague
 
Programming Android
Programming AndroidProgramming Android
Programming Androidleague
 
Futzing with actors (etc.)
Futzing with actors (etc.)Futzing with actors (etc.)
Futzing with actors (etc.)league
 

More from league (6)

On the Edge, 2013
On the Edge, 2013On the Edge, 2013
On the Edge, 2013
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Language
 
On the edge
On the edgeOn the edge
On the edge
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
 
Programming Android
Programming AndroidProgramming Android
Programming Android
 
Futzing with actors (etc.)
Futzing with actors (etc.)Futzing with actors (etc.)
Futzing with actors (etc.)
 

Recently uploaded

Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructureitnewsafrica
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 

Recently uploaded (20)

Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 

Here is how you could write this as a for comprehension:for { venue <- lookupVenue("The Dancing Ferret") user <- getLoggedInUser(sessionId) confNo <- reserveTable(venue, user)} yield confNoThis translates each operation to a flatMap, sequencing the computations so that if any operation returns None, the whole computation short-circuits without evaluating the remaining steps.So monads like Option allow modeling failure/exceptions in a composable way. Monad laws:Left identity: unit(x).flatMap(f) == f(x)Right identity: m.flatMap(unit) == m

  • 1. Monadologie — professional help for type anxiety Christopher League 12 July 2010
  • 2. Monadologie — github.com/league/scala-type-anxiety @chrisleague league@contrapunctus.net
  • 4.
  • 5.
  • 7. “Java might be the vehicle Principles of that will help us carry Programming modern programming language innovations Languages into industrial practice.” – me January 1997 § Paris
  • 9. Monadologie continuations monads existentials variance effects
  • 10. Monadologie continuations – control flow monads – data flow
  • 11.
  • 12.
  • 15. def plus [A] (x: Int, y: Int, k: Int=>A): A = k(x+y) def times [A] (x: Int, y: Int, k: Int=>A): A = k(x*y) def less [A] (x: Int, y: Int, kt: => A, kf: => A): A = if(x < y) kt else kf
  • 16. def factorial [A] (n: Int, k: Int => A): A = less(n, 2, k(1), plus(n, -1, (m:Int) => factorial(m, (f:Int) => times(n, f, k)))) scala> factorial(5, println) 120 scala> factorial(3, factorial(_, println)) 720 scala> val n = factorial(3, r => r) n: Int = 6
  • 18. class Regex case class Literal(s: String) extends Regex case class Concat(r1: Regex, r2: Regex) extends Regex case class Choice(r1: Regex, r2: Regex) extends Regex case class Star(r: Regex) extends Regex Concat(Star(Literal("ab")), Literal("abc")) // (ab*)abc matches abababc Choice(Star(Literal("ab")), Concat(Literal("a"), Star(Literal("ba")))) // (ab)*|a(ba)* matches abababa
  • 19. def accept (regex: Regex, chars: Seq[Char], k: Seq[Char] => Boolean): Boolean = regex match { case Literal(expect) => if(chars.take(expect.length).sameElements(expect)) k(chars.drop(expect.length)) else false case Concat(regex1, regex2) => accept(regex1, chars, remaining => accept(regex2, remaining, k)) case Choice(regex1, regex2) => accept(regex1, chars, k) || accept(regex2, chars, k) case Star(repeatable) => k(chars) || accept(repeatable, chars, remaining => accept(regex, remaining, k)) }
  • 20. def accept (regex: Regex, chars: Seq[Char], k: Seq[Char] => Boolean): Boolean = ... def complete (remaining: Seq[Char]): Boolean = remaining.length == 0 accept(regex1, "abababc", complete) // true accept(regex2, "abababa", complete) // true accept(regex1, "abababcd", complete) // false
  • 22. Delimited Continuations shift & reset
  • 23. def doSomething0 = reset { println("Ready?") val result = 1 + special * 3 println(result) } Punch a hole in your code. What type of value is expected in the hole? What happens after the hole? What is result type of the reset block?
  • 24. def doSomething0 = reset { println("Ready?") val result = 1 + special * 3 println(result) } Think of the rest of the computation as a function with the hole as its parameter. Call it the continuation.
  • 25. def doSomething1 = reset { println("Ready?") val result = 1 + special * 3 println(result) } def special = shift { k: (Int => Unit) => println(99) "Gotcha!" shift captures the continuation and } then determines its own future.
  • 26. def doSomething1 = reset { println("Ready?") val result = 1 + special * 3 println(result) } def special = shift { k: (Int => Unit) => println(99) "Gotcha!" shift doSomething1 scala> captures the continuation and } Ready?determines its own future. then 99 res0: java.lang.String = Gotcha!
  • 27. def doSomething2 = reset { println("Ready?") val result = 1 + wacky * 3 println(result) } def wacky = shift { k: (Int => Unit) => k(2) println("Yo!") k(3) }
  • 28. def doSomething2 = reset { println("Ready?") val result = 1 + wacky * 3 println(result) } def wacky = shift { k: (Int => Unit) => k(2) println("Yo!") scala> doSomething2 k(3) Ready? } 7 Yo! 10
  • 29. Continuation low-level control-flow primitive that can implement: exceptions concurrency (actors) suspensions (lazy) …
  • 30. def multi = reset { println("This function returns tentatively") println("but you can always ask for more.") produce(42) println("Didn't like that? Back again.") produce(99) println("Still not OK? I'm out of ideas!") None }
  • 31. def multi = reset { println("This function returns tentatively") println("but you can always ask for more.") produce(42) println("Didn't like that? Back again.") scala> multi produce(99) function returns tentatively This println("Still can alwaysI'm out more. but you not OK? ask for of ideas!") None res0: Option[ReturnThunk[Int]] = Some(...) } scala> println(res0.get.value) 42 scala> res0.get.proceed Didn’t like that? Back again. res1: Option[ReturnThunk[Int]] = Some(...) scala> println(res1.get.value) 99 scala> res1.get.proceed Still not OK? I’m out of ideas! res2: Option[ReturnThunk[Int]] = None
  • 32. def multi = reset { println("This function returns tentatively") println("but you can always ask for more.") produce(42) println("Didn't like that? Back again.") produce(99) println("Still not OK? I'm out of ideas!") None }
  • 33. case class ReturnThunk[A] (value: A, proceed: Unit => Option[ReturnThunk[A]]) def produce [A] (value: A): Unit @cps[Option[ReturnThunk[A]]] = shift { k: (Unit => Option[ReturnThunk[A]]) => Some(ReturnThunk(value, k)) } def multi = reset { println("This function returns tentatively") println("but you can always ask for more.") produce(42) println("Didn't like that? Back again.") produce(99) println("Still not OK? I'm out of ideas!") None }
  • 34. def interact = reset { val first = ask("Please give me a number") val second = ask("Enter another number") printf("The sum of your numbers is: %dn", first + second) }
  • 35. def interact = reset { val first = ask("Please give me a number") val second = ask("Enter another number") printf("The sum of your numbers is: %dn", first + second) } scala> interact Please give me a number respond with: submit(0x28d092b7, ...) scala> submit(0x28d092b7, 14) Enter another number respond with: submit(0x1ddb017b, ...) scala> submit(0x1ddb017b, 28) The sum of your numbers is: 42
  • 36. type UUID = Int def uuidGen: UUID = Random.nextInt type Data = Int val sessions = new HashMap[UUID, Data=>Unit] def ask(prompt: String): Data @cps[Unit] = shift { k: (Data => Unit) => { val id = uuidGen printf("%snrespond with: submit(0x%x, ...)n", prompt, id) sessions += id -> k } } def submit(id: UUID, data: Data) = sessions(id)(data) def interact = reset { val first = ask("Please give me a number") val second = ask("Enter another number") printf("The sum of your numbers is: %dn", first + second) }
  • 38. def harmful = reset { var i = 0 println("Hello world!") label("loop") println(i) i = i + 1 if(i < 20) goto("loop") println("Done.") }
  • 39. def harmful = reset { var i = 0 println("Hello world!") Hello world! label("loop") 0 println(i) 1 i = i + 1 2 . if(i < 20) goto("loop") . println("Done.") . } 18 19 Done.
  • 40. def harmful = reset { var i = 0 println("Hello world!") label("loop") println(i) i = i + 1 if(i < 20) goto("loop") println("Done.") }
  • 41. val labelMap = new HashMap[String, Unit=>Unit] def label(name:String) = shift { k:(Unit=>Unit) => labelMap += name -> k k() } def goto(name:String) = shift { k:(Unit=>Unit) => labelMap(name)() } def harmful = reset { var i = 0 println("Hello world!") label("loop") println(i) i = i + 1 if(i < 20) goto("loop") println("Done.") }
  • 42. Monads the leading design pattern for functional programming
  • 43. A type constructor M is a monad if it supports these operations: def unit[A] (x: A): M[A] def flatMap[A,B] (m: M[A]) (f: A => M[B]): M[B] def map[A,B] (m: M[A]) (f: A => B): M[B] = flatMap(m){ x => unit(f(x)) } def andThen[A,B] (ma: M[A]) (mb: M[B]): M[B] = flatMap(ma){ x => mb }
  • 44. Option is a monad. def unit[A] (x: A): Option[A] = Some(x) def flatMap[A,B](m:Option[A])(f:A =>Option[B]): Option[B] = m match { case None => None case Some(x) => f(x) }
  • 45. List is a monad. def unit[A] (x: A): List[A] = List(x) def flatMap[A,B](m:List[A])(f:A =>List[B]): List[B] = m match { case Nil => Nil case x::xs => f(x) ::: flatMap(xs)(f) }
  • 46. For comprehension: convenient syntax for monadic structures. for(i <- 1 to 4; j <- 1 to i; k <- 1 to j) yield { i*j*k } Compiler translates it to: (1 to 4).flatMap { i => (1 to i).flatMap { j => (1 to j).map { k => i*j*k }}}
  • 47. Example: a series of operations, where each may fail. lookupVenue: String => Option[Venue] getLoggedInUser: SessionID => Option[User] reserveTable: (Venue, User) => Option[ConfNo]
  • 48. Example: a series of operations, where each may fail. lookupVenue: String => Option[Venue] getLoggedInUser: SessionID => Option[User] reserveTable: (Venue, User) => Option[ConfNo] val user = getLoggedInUser(session) val confirm = if(!user.isDefined) { None } else lookupVenue(name) match { case None => None case Some(venue) => { val confno = reserveTable(venue, user.get) if(confno.isDefined) mailTo(confno.get, user.get) confno } }
  • 49. Example: a series of operations, where each may fail. lookupVenue: String => Option[Venue] getLoggedInUser: SessionID => Option[User] reserveTable: (Venue, User) => Option[ConfNo] val user = getLoggedInUser(session) val confirm = if(!user.isDefined) { None } else lookupVenue(name) match { case None => None case Some(venue) => { val confno = reserveTable(venue, user.get) if(confno.isDefined) mailTo(confno.get, user.get) confno } }
  • 50. Example: a series of operations, where each may fail. lookupVenue: String => Option[Venue] getLoggedInUser: SessionID => Option[User] reserveTable: (Venue, User) => Option[ConfNo] val confirm = for(venue <- lookupVenue(name); user <- getLoggedInUser(session); confno <- reserveTable(venue, user)) yield { mailTo(confno, user) confno }
  • 51. Example from Lift form validation: def addUser(): Box[UserInfo] = for { firstname <- S.param("firstname") ?~ "firstname parameter missing" ~> 400 lastname <- S.param("lastname") ?~ "lastname parameter missing" email <- S.param("email") ?~ "email parameter missing" } yield { val u = User.create.firstName(firstname). lastName(lastname).email(email) S.param("password") foreach u.password.set u.saveMe }
  • 52. Example: use monad to pass around state behind the scenes class Tree[A] case class Leaf[A](elem: A) extends Tree[A] case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A] inject(‘Q’, ) => f a Q c d b f g e c h g d e a h
  • 53. def inject[A] (root: Tree[A], cur: A): (Tree[A], A) = root match { case Leaf(old) => (Leaf(cur), old) case Branch(left, right) => val (t1, last1) = inject(left, cur) val (t2, last2) = inject(right, last1) (Branch(t1,t2), last2) }
  • 54. def inject[A] (root: Tree[A], cur: A): (Tree[A], A) = root match { case Leaf(old) => (Leaf(cur), old) case Branch(left, right) => val (t1, last1) = inject(left, cur) val (t2, last2) = inject(right, last1) (Branch(t1,t2), last2) } def injectST[A] (root: Tree[A]): ST[A, Tree[A]] = root match { case Leaf(old) => for(cur <- init[A]; u <- update[A](_ => old)) yield Leaf(cur) case Branch(left, right) => for(t1 <- injectST(left); t2 <- injectST(right)) yield Branch(t1,t2) }
  • 55. case class ST[S,A](exec: S => (S,A)) { def flatMap[B] (f: A => ST[S,B]): ST[S,B] = ST { s0 => val (s1, a) = exec(s0) f(a).exec(s1) } def map[B] (f: A => B) (implicit unit: B => ST[S,B]) : ST[S,B] = flatMap { x => unit(f(x)) } } implicit def unitST[S,A] (x: A): ST[S,A] = ST { s0 => (s0, x) } def init[S]: ST[S,S] = ST { s0 => (s0, s0) } def update[S] (g: S => S): ST[S,Unit] = ST { s0 => (g(s0), ()) }
  • 56. case class ST[S,A](exec: S => (S,A)) { def flatMap[B] (f: scala> ST[S,B]): ST[S,B] = A => drawTree(t1,"") ST { s0 => ______f | _____d val (s1, a) = exec(s0) | _____e f(a).exec(s1) | __c } _____a ________h | __g def map[B] (f: A => B) __b (implicit unit: B => ST[S,B]) : ST[S,B] = flatMap { x => unit(f(x)) m }= injectST(t1) scala> val m: ST[Char,Tree[Char]] = ST(<function1>) } scala> val (_,t2) = m.exec('Q') t2: Tree[Char] = ... implicit def unitST[S,A] (x: A): ST[S,A] = ST { s0 => (s0, x) scala> drawTree(t2,"") } ______Q def init[S]: ST[S,S] | _____f = | _____d ST { s0 => (s0, s0)| } __e _____c ________a def update[S] (g: S => S): ST[S,Unit] | __h = ST { s0 => (g(s0), ()) } __g
  • 57.
  • 58. Monadologie github.com/league/scala-type-anxiety @chrisleague league@contrapunctus.net