SlideShare a Scribd company logo
Monadologie —
  professional help for
          type anxiety

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




                @chrisleague
          league@contrapunctus.net
1996
Monadologie
Monadologie
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
Monadologie
Monadologie
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
Monadologie
github.com/league/scala-type-anxiety




                @chrisleague
          league@contrapunctus.net

More Related Content

What's hot

Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)
Scott Wlaschin
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
Scott Wlaschin
 
Aljabar boolean
Aljabar booleanAljabar boolean
Aljabar boolean
farhan2000
 
Haskell vs. F# vs. Scala
Haskell vs. F# vs. ScalaHaskell vs. F# vs. Scala
Haskell vs. F# vs. Scala
pt114
 
Ruang Dimensi 3 (Jarak Pada Bangun Ruang)
Ruang Dimensi 3 (Jarak Pada Bangun Ruang)Ruang Dimensi 3 (Jarak Pada Bangun Ruang)
Ruang Dimensi 3 (Jarak Pada Bangun Ruang)
saddam_123
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
Debasish Ghosh
 
Scala collection
Scala collectionScala collection
Scala collection
Knoldus Inc.
 
Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!
Jorge Vásquez
 
APEX JET Charts: Data Viz now!
APEX JET Charts:  Data Viz now!APEX JET Charts:  Data Viz now!
APEX JET Charts: Data Viz now!
Karen Cannell
 
Matematika Diskrit : Himpunan
Matematika Diskrit : HimpunanMatematika Diskrit : Himpunan
Matematika Diskrit : Himpunan
Herbert Abdillah
 
ATG Advanced RQL
ATG Advanced RQLATG Advanced RQL
ATG Advanced RQL
Kate Semizhon
 
itft-Inheritance in java
itft-Inheritance in javaitft-Inheritance in java
itft-Inheritance in java
Atul Sehdev
 
Matematika Diskrit - 03 himpunan - 04
Matematika Diskrit - 03 himpunan -  04Matematika Diskrit - 03 himpunan -  04
Matematika Diskrit - 03 himpunan - 04
KuliahKita
 
Friend function & friend class
Friend function & friend classFriend function & friend class
Friend function & friend class
Abhishek Wadhwa
 
Fungsi Rekursif
Fungsi RekursifFungsi Rekursif
Fungsi Rekursif
Nida Shafiyanti
 
17 tangent planes and total differentials
17 tangent planes and total differentials17 tangent planes and total differentials
17 tangent planes and total differentials
math267
 
What is OOP?
What is OOP?What is OOP?
What is OOP?
Amin Uddin
 
06 laboratory exercise 1
06 laboratory exercise 106 laboratory exercise 1
06 laboratory exercise 1
Anne Lee
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
Scott Wlaschin
 
Matlab 4
Matlab 4Matlab 4
Matlab 4
Hastih Leo
 

What's hot (20)

Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
 
Aljabar boolean
Aljabar booleanAljabar boolean
Aljabar boolean
 
Haskell vs. F# vs. Scala
Haskell vs. F# vs. ScalaHaskell vs. F# vs. Scala
Haskell vs. F# vs. Scala
 
Ruang Dimensi 3 (Jarak Pada Bangun Ruang)
Ruang Dimensi 3 (Jarak Pada Bangun Ruang)Ruang Dimensi 3 (Jarak Pada Bangun Ruang)
Ruang Dimensi 3 (Jarak Pada Bangun Ruang)
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
Scala collection
Scala collectionScala collection
Scala collection
 
Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!
 
APEX JET Charts: Data Viz now!
APEX JET Charts:  Data Viz now!APEX JET Charts:  Data Viz now!
APEX JET Charts: Data Viz now!
 
Matematika Diskrit : Himpunan
Matematika Diskrit : HimpunanMatematika Diskrit : Himpunan
Matematika Diskrit : Himpunan
 
ATG Advanced RQL
ATG Advanced RQLATG Advanced RQL
ATG Advanced RQL
 
itft-Inheritance in java
itft-Inheritance in javaitft-Inheritance in java
itft-Inheritance in java
 
Matematika Diskrit - 03 himpunan - 04
Matematika Diskrit - 03 himpunan -  04Matematika Diskrit - 03 himpunan -  04
Matematika Diskrit - 03 himpunan - 04
 
Friend function & friend class
Friend function & friend classFriend function & friend class
Friend function & friend class
 
Fungsi Rekursif
Fungsi RekursifFungsi Rekursif
Fungsi Rekursif
 
17 tangent planes and total differentials
17 tangent planes and total differentials17 tangent planes and total differentials
17 tangent planes and total differentials
 
What is OOP?
What is OOP?What is OOP?
What is OOP?
 
06 laboratory exercise 1
06 laboratory exercise 106 laboratory exercise 1
06 laboratory exercise 1
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
Matlab 4
Matlab 4Matlab 4
Matlab 4
 

Similar to Monadologie

Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
Stephan Janssen
 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
league
 
(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
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
Christian Baranowski
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
Eelco Visser
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
scalaconfjp
 
Parametricity - #cljsyd - May, 2015
Parametricity - #cljsyd - May, 2015Parametricity - #cljsyd - May, 2015
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
Hang Zhao
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Aleksandar Prokopec
 
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
SeniorDevOnly
 
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
Eleanor McHugh
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
Arturo Herrero
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
Wojciech Pituła
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using Scala
Siarhiej Siemianchuk
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
pramode_ce
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
Baruch Sadogursky
 

Similar to Monadologie (20)

Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
 
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
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
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
 

More from league

On the Edge, 2013
On the Edge, 2013On the Edge, 2013
On the Edge, 2013
league
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Language
league
 
On the edge
On the edgeOn the edge
On the edge
league
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
league
 
Programming Android
Programming AndroidProgramming Android
Programming Android
league
 
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

How to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptxHow to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptx
Adam Dunkels
 
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptxIntroduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
313mohammedarshad
 
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
Torry Harris
 
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdfWhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
ArgaBisma
 
"Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes...
"Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes..."Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes...
"Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes...
Anant Gupta
 
Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024
aakash malhotra
 
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
Priyanka Aash
 
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptxDublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Kunal Gupta
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
Matthias Neugebauer
 
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
maigasapphire
 
Choose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presenceChoose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presence
rajancomputerfbd
 
Using LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and MilvusUsing LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and Milvus
Zilliz
 
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
aslasdfmkhan4750
 
The Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF GuideThe Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF Guide
Shiv Technolabs
 
BT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdf
BT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdfBT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdf
BT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdf
Neo4j
 
Tirana Tech Meetup - Agentic RAG with Milvus, Llama3 and Ollama
Tirana Tech Meetup - Agentic RAG with Milvus, Llama3 and OllamaTirana Tech Meetup - Agentic RAG with Milvus, Llama3 and Ollama
Tirana Tech Meetup - Agentic RAG with Milvus, Llama3 and Ollama
Zilliz
 
July Patch Tuesday
July Patch TuesdayJuly Patch Tuesday
July Patch Tuesday
Ivanti
 
WhatsApp Spy Online Trackers and Monitoring Apps
WhatsApp Spy Online Trackers and Monitoring AppsWhatsApp Spy Online Trackers and Monitoring Apps
WhatsApp Spy Online Trackers and Monitoring Apps
HackersList
 
WPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide DeckWPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide Deck
Lidia A.
 
The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...
The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...
The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...
digitalxplive
 

Recently uploaded (20)

How to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptxHow to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptx
 
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptxIntroduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
 
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
 
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdfWhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
 
"Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes...
"Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes..."Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes...
"Mastering Graphic Design: Essential Tips and Tricks for Beginners and Profes...
 
Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024
 
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
 
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptxDublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
 
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
 
Choose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presenceChoose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presence
 
Using LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and MilvusUsing LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and Milvus
 
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
 
The Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF GuideThe Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF Guide
 
BT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdf
BT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdfBT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdf
BT & Neo4j: Knowledge Graphs for Critical Enterprise Systems.pptx.pdf
 
Tirana Tech Meetup - Agentic RAG with Milvus, Llama3 and Ollama
Tirana Tech Meetup - Agentic RAG with Milvus, Llama3 and OllamaTirana Tech Meetup - Agentic RAG with Milvus, Llama3 and Ollama
Tirana Tech Meetup - Agentic RAG with Milvus, Llama3 and Ollama
 
July Patch Tuesday
July Patch TuesdayJuly Patch Tuesday
July Patch Tuesday
 
WhatsApp Spy Online Trackers and Monitoring Apps
WhatsApp Spy Online Trackers and Monitoring AppsWhatsApp Spy Online Trackers and Monitoring Apps
WhatsApp Spy Online Trackers and Monitoring Apps
 
WPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide DeckWPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide Deck
 
The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...
The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...
The Rise of AI in Cybersecurity How Machine Learning Will Shape Threat Detect...
 

Monadologie

  • 1. Monadologie — professional help for type anxiety Christopher League 12 July 2010
  • 2. Monadologie — github.com/league/scala-type-anxiety @chrisleague league@contrapunctus.net
  • 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
  • 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
  • 58. Monadologie github.com/league/scala-type-anxiety @chrisleague league@contrapunctus.net