SlideShare a Scribd company logo
Continuations
 and other Functional Patterns

      Christopher League
        Long Island University



      Northeast Scala Symposium
           February 
Sin & redemption
Scala Functional Patterns
Scala Functional Patterns
Java classes → SML runtime
Standard ML of New Jersey v110.30 [JFLINT 1.2]
- Java.classPath := [”/home/league/r/java/tests”];
val it = () : unit
- val main = Java.run ”Hello”;
[parsing Hello]
[parsing java/lang/Object]
[compiling java/lang/Object]
[compiling Hello]
[initializing java/lang/Object]
[initializing Hello]
val main = fn : string list -> unit
- main [”World”];
Hello, World
val it = () : unit
- main [];
uncaught exception ArrayIndexOutOfBounds
  raised at: Hello.main([Ljava/lang/String;)V
- ˆD
OO runtime ← functional languages

              Scala
             Clojure
               F
               etc.
Patterns
. Continuation-passing style
. Format combinators
. Nested data types


                    eme
  Higher-order {functions, types}
Pattern : Continuations
A continuation is an argument that represents
the rest of the computation meant to occur
after the current function.
Explicit continuations – straight-line
 def greeting [A] (name: String) (k: => A): A =
   printk(”Hello, ”) {
   printk(name) {
   printk(”!n”)(k)
   }}
 def printk [A] (s: String) (k: => A): A =
   { Console.print(s); k }

scala> greeting(”Scala peeps”) { true }
Hello, Scala peeps!
res0: Boolean = true
Pay it forward...
Current function can ‘return’ a value
by passing it as a parameter to its continuation.
Explicit continuations – return values
 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 test[A](k: String => A): A =
   plus(3,2) { a => times(3,2) { b =>
   less(a,b) {k(”yes”)} {k(”no”)} }}

scala> test{printk(_){}}
yes
Delimited continuations
reset Serves as delimiter for CPS transformation.
shift Captures current continuation as a function
      (up to dynamically-enclosing reset)
      then runs specified block instead.
Delimited continuations
def doSomething0 = reset {
  println(”Ready?”)
  val result = 1 + ˜˜˜˜˜˜˜˜ * 3
  println(result)
}
ink of the rest of the computation
as a function with the hole as its parameter.
Delimited continuations
def doSomething1 = reset {
  println(”Ready?”)
  val result = 1 + special * 3
  println(result)
}
def special = shift {
  k: (Int => Unit) => println(99); ”Gotcha!”
}
shift captures continuation as k
and then determines its own future.
Delimited continuations
def doSomething1 = reset {
  println(”Ready?”)
  val result = 1 + special * 3
  println(result)
}
def special = shift {
  k: (Int => Unit) => println(99); ”Gotcha!”
}

scala> doSomething1
Ready?
99
res0: java.lang.String = Gotcha!
Continuation-based user interaction
def interact = reset {
  val a = ask(”Please give me a number”)
  val b = ask(”Please enter another number”)
  printf(”The sum of your numbers is: %dn”, a+b)
}

scala> interact
Please give me a number
answer using: submit(0xa9db9535, ...)
scala> submit(0xa9db9535, 14)
Please enter another number
answer using: submit(0xbd1b3eb0, ...)
scala> submit(0xbd1b3eb0, 28)
The sum of your numbers is: 42
Continuation-based user interaction
val sessions = new HashMap[UUID, Int=>Unit]
def ask(prompt: String): Int @cps[Unit] = shift {
    k: (Int => Unit) => {
      val id = uuidGen
      printf(”%snanswer using: submit(0x%x, ...)n”,
            prompt, id)
      sessions += id -> k
  }}
def submit(id: UUID, data: Int) = sessions(id)(data)

def interact = reset {
  val a = ask(”Please give me a number”)
  val b = ask(”Please enter another number”)
  printf(”The sum of your numbers is: %dn”, a+b)
}
Pattern : Format combinators
                                             [Danvy ]
Typeful programmers covet printf.
  int a = 5;
  int b = 2;
  float c = a / (float) b;
  printf(”%d over %d is %.2fn”, a, b, c);
Cannot type-check because format is just a string.
What if it has structure, like abstract syntax tree?
Typed format specifiers
 val frac: Int => Int => Float => String =
   d & ” over ” & d & ” is ” & f(2) & endl |
 val grade: Any => Double => Unit =
   ”Hello, ”&s&”: your exam score is ”&pct&endl |>
 val hex: (Int, Int, Int) => String =
   uncurried(”#”&x&x&x|)
                  (Type annotations are for reference – not required.)

scala> println(uncurried(frac)(a,b,c))
5 over 2 is 2.50

scala> grade(”Joshua”)(0.97)
Hello, Joshua: your exam score is 97%
scala> println(”Roses are ”&s | hex(250, 21, 42))
Roses are #fa152a
Buffer representation
type Buf = List[String]
def put(b: Buf, e: String): Buf = e :: b
def finish(b: Buf): String = b.reverse.mkString
def initial: Buf = Nil
Operational semantics
def lit(m:String)(k:Buf=>A)(b:Buf) = k(put(b,m))
def x(k:Buf=>A)(b:Buf)(i:Int) = k(put(b,i.toHexString))
def s(k:Buf=>A)(b:Buf)(o:Any) = k(put(b,o.toString))
                             (Not the actual implementation.)

         lit(”L”)(finish)(initial)      ”L”
         x(finish)(initial)(42)         ”2a”

where:
 type Buf = List[String]
 def put(b: Buf, e: String): Buf = e :: b
 def finish(b: Buf): String = b.reverse.mkString
 def initial: Buf = Nil
Function composition
 (lit(”L”) & x) (finish) (initial) (2815)

 lit(”L”)(x(finish)) (initial) (2815)

lit(”L”)(λ b0.λ i.finish(i.toHex :: b0)) (initial) (2815)

(λ b1.λ i.finish(i.toHex :: ”L” :: b1)) (initial) (2815)
       finish(2815.toHex :: ”L” :: initial)
          List(”aff”,”L”).reverse.mkString      ”Laff”
where:
def lit(m:String)(k:Buf=>A)(b:Buf) = k(put(b,m))
def x(k:Buf=>A)(b:Buf)(i:Int) = k(put(b,i.toHexString))
def s(k:Buf=>A)(b:Buf)(o:Any) = k(put(b,o.toString))
Combinator polymorphism
What is the answer type?
      x: ∀A.(Buf => A) => Buf => Int => A
 finish: Buf => String

          x(x(x(finish)))
                A	≡ String
              A	≡ Int	=>	String
            A	≡ Int	=>	Int	=>	String
Type constructor polymorphism
trait Compose[F[_],G[_]] { type T[X] = F[G[X]] }
trait Fragment[F[_]] {
  def apply[A](k: Buf=>A): Buf=>F[A]
  def & [G[_]] (g: Fragment[G]) =
    new Fragment[Compose[F,G]#T] {
      def apply[A](k: Buf=>A) = Fragment.this(g(k))
    }
  def | : F[String] = apply(finish(_))(initial)
}
Combinator implementations
type Id[A] = A
implicit def lit(s:String) = new Fragment[Id] {
  def apply[A](k: Cont[A]) = (b:Buf) => k(put(b,s))
}

type IntF[A] = Int => A
val x = new Fragment[IntF] {
  def apply[A](k: Cont[A]) = (b:Buf) => (i:Int) =>
    k(put(b,i.toHexString))
}
Pattern : Nested data types
Usually, a polymorphic recursive data type
is instantiated uniformly throughout:
trait List[A]
case class Nil[A]() extends List[A]
case class Cons[A](hd:A, tl:List[A]) extends List[A]
What if type parameter of recursive invocation differs?
Weird examples
trait Weird[A]
case class Wil[A]() extends Weird[A]
case class Wons[A](hd: A, tl: Weird[(A,A)])
extends Weird[A] // tail of Weird[A] is Weird[(A,A)]

val z: Weird[Int] = Wons(1, Wil[I2]())
val y: Weird[Int] = Wons(1, Wons((2,3), Wil[I4]))
val x: Weird[Int] =
       Wons( 1,
       Wons( (2,3),
       Wons( ((4,5),(6,7)),
       Wil[I8]())))

type I2 = (Int,Int)
type I4 = (I2,I2)
type I8 = (I4,I4)
Square matrices
                                     [Okasaki ]
Vector[Vector[A]] is a two-dimensional matrix
of elements of type A.
But lengths of rows (inner vectors) could differ.
Using nested data types, recursively build
a type constructor V[_] to represent a sequence
of a fixed number of elements.
en, Vector[V[A]] is a well-formed matrix,
and V[V[A]] is square.
Square matrix example
scala> val m = tabulate(6){(i,j) => (i+1)*(j+1)}
m: FastExpSquareMatrix.M[Int] =
  Even Odd Odd Zero (((),((((),(1,2)),((3,4),(5,6))
  ),(((),(2,4)),((6,8),(10,12))))),(((((),(3,6)),((
  9,12),(15,18))),(((),(4,8)),((12,16),(20,24)))),(
  (((),(5,10)),((15,20),(25,30))),(((),(6,12)),((18
  ,24),(30,36))))))
scala> val q = m(4,2)
q: Int = 15
scala> val m2 = m updated (4,2,999)
m2: FastExpSquareMatrix.M[Int] =
  Even Odd Odd Zero (((),((((),(1,2)),((3,4),(5,6))
  ),(((),(2,4)),((6,8),(10,12))))),(((((),(3,6)),((
  9,12),(15,18))),(((),(4,8)),((12,16),(20,24)))),(
  (((),(5,10)),((999,20),(25,30))),(((),(6,12)),((
  18,24),(30,36))))))
Analogy with fast exponentiation
fastexp r b 0 = r
fastexp r b n = fastexp r (b2 ) n/2         if n even
fastexp r b n = fastexp (r · b) (b2 ) n/2   otherwise
For example:
 fastexp 1 b 6 =                        Even
 fastexp 1 (b2 ) 3 =                    Odd
                      2
 fastexp (1 · b2 ) (b2 ) 1 =            Odd
                   2      22
fastexp (1 · b2 · b2 ) (b2 ) 0 =        Zero
            2
1 · b2 · b2
Fast exponentiation of product types
type U = Unit
type I = Int
fastExp U I 6 =                        //   Even
fastExp U (I,I) 3 =                    //   Odd
fastExp (U,(I,I)) ((I,I),(I,I)) 1 =    //   Odd
fastExp ((U,(I,I)),((I,I),(I,I)))      //   Zero
       (((I,I),(I,I)),((I,I),(I,I))) 0 =
((U,(I,I)),((I,I),(I,I)))
Implementation as nested data type
trait Pr[V[_], W[_]] {
  type T[A] = (V[A],W[A])
}
trait M [V[_],W[_],A]
case class Zero [V[_],W[_],A] (data: V[V[A]])
     extends M[V,W,A]
case class Even [V[_],W[_],A] (
           next: M[V, Pr[W,W]#T, A]
     ) extends M[V,W,A]
case class Odd [V[_],W[_],A] (
           next: M[Pr[V,W]#T, Pr[W,W]#T, A]
     ) extends M[V,W,A]

type Empty[A] = Unit
type Id[A] = A
type Matrix[A] = M[Empty,Id,A]
anks!
           league@contrapunctus.net
                 @chrisleague




github.com/league/                 slidesha.re/eREMXZ
scala-fun-patterns
   Danvy, Olivier. “Functional Unparsing” J. Functional
   Programming (), .
   Okasaki, Chris. “From Fast Exponentiation to Square
   Matrices: An Adventure in Types” Int’l Conf. Functional
   Programming, .

More Related Content

PDF
Oh, All the things you'll traverse
PDF
Monoids, monoids, monoids
PDF
Testing in the World of Functional Programming
PDF
Monoids, Monoids, Monoids - ScalaLove 2020
PDF
Traversals for all ocasions
PDF
Principled Error Handling with FP
PDF
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
PDF
A tour of Python
Oh, All the things you'll traverse
Monoids, monoids, monoids
Testing in the World of Functional Programming
Monoids, Monoids, Monoids - ScalaLove 2020
Traversals for all ocasions
Principled Error Handling with FP
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
A tour of Python

What's hot (18)

PDF
First-Class Patterns
PPTX
Introduction to Monads in Scala (1)
PDF
One Monad to Rule Them All
PPTX
Introduction to Monads in Scala (2)
ODP
Functions In Scala
PDF
Scala. Introduction to FP. Monads
PDF
Functional programming with haskell
PDF
Python lecture 05
PDF
7 Habits For a More Functional Swift
PDF
Humble introduction to category theory in haskell
PDF
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
PDF
Reasoning about laziness
PDF
Python programming : Standard Input and Output
PDF
Java cheatsheet
ODP
Effective way to code in Scala
PDF
The java language cheat sheet
ODP
Type Parameterization
PDF
Introduction to haskell
First-Class Patterns
Introduction to Monads in Scala (1)
One Monad to Rule Them All
Introduction to Monads in Scala (2)
Functions In Scala
Scala. Introduction to FP. Monads
Functional programming with haskell
Python lecture 05
7 Habits For a More Functional Swift
Humble introduction to category theory in haskell
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Reasoning about laziness
Python programming : Standard Input and Output
Java cheatsheet
Effective way to code in Scala
The java language cheat sheet
Type Parameterization
Introduction to haskell
Ad

Viewers also liked (7)

PDF
Futzing with actors (etc.)
PDF
Futures and Rx Observables: powerful abstractions for consuming web services ...
PDF
Building microservices with Scala, functional domain models and Spring Boot (...
PDF
Reactive Spring Framework 5
PDF
Reactive Programming in Spring 5
PDF
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
PDF
Building microservices with Scala, functional domain models and Spring Boot
Futzing with actors (etc.)
Futures and Rx Observables: powerful abstractions for consuming web services ...
Building microservices with Scala, functional domain models and Spring Boot (...
Reactive Spring Framework 5
Reactive Programming in Spring 5
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Building microservices with Scala, functional domain models and Spring Boot
Ad

Similar to Scala Functional Patterns (20)

PDF
Fp in scala with adts part 2
PPTX
The Essence of the Iterator Pattern
PDF
Monadologie
PDF
The Essence of the Iterator Pattern (pdf)
PDF
Power of functions in a typed world
PDF
Fp in scala part 2
PDF
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
KEY
An Introduction to Functional Programming using Haskell
PDF
Modular Module Systems
PDF
(How) can we benefit from adopting scala?
PPTX
Scala best practices
PPTX
Scala - where objects and functions meet
PDF
Scalapeno18 - Thinking Less with Scala
PDF
Go: It's Not Just For Google
PDF
Functions, Types, Programs and Effects
PDF
Go a crash course
PPTX
API design: using type classes and dependent types
PDF
Generic Functional Programming with Type Classes
PDF
Drinking the free kool-aid
PDF
An overview of Python 2.7
Fp in scala with adts part 2
The Essence of the Iterator Pattern
Monadologie
The Essence of the Iterator Pattern (pdf)
Power of functions in a typed world
Fp in scala part 2
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
An Introduction to Functional Programming using Haskell
Modular Module Systems
(How) can we benefit from adopting scala?
Scala best practices
Scala - where objects and functions meet
Scalapeno18 - Thinking Less with Scala
Go: It's Not Just For Google
Functions, Types, Programs and Effects
Go a crash course
API design: using type classes and dependent types
Generic Functional Programming with Type Classes
Drinking the free kool-aid
An overview of Python 2.7

Recently uploaded (20)

PDF
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
PPT
Teaching material agriculture food technology
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PPTX
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
PDF
Advanced IT Governance
PDF
cuic standard and advanced reporting.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Cloud computing and distributed systems.
PDF
KodekX | Application Modernization Development
PPTX
Big Data Technologies - Introduction.pptx
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Modernizing your data center with Dell and AMD
PDF
Machine learning based COVID-19 study performance prediction
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Sensors and Actuators in IoT Systems using pdf
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
Teaching material agriculture food technology
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
Advanced IT Governance
cuic standard and advanced reporting.pdf
Spectral efficient network and resource selection model in 5G networks
Cloud computing and distributed systems.
KodekX | Application Modernization Development
Big Data Technologies - Introduction.pptx
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Modernizing your data center with Dell and AMD
Machine learning based COVID-19 study performance prediction
Chapter 3 Spatial Domain Image Processing.pdf
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Sensors and Actuators in IoT Systems using pdf
NewMind AI Monthly Chronicles - July 2025
Reach Out and Touch Someone: Haptics and Empathic Computing
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...

Scala Functional Patterns

  • 1. Continuations and other Functional Patterns Christopher League Long Island University Northeast Scala Symposium  February 
  • 5. Java classes → SML runtime Standard ML of New Jersey v110.30 [JFLINT 1.2] - Java.classPath := [”/home/league/r/java/tests”]; val it = () : unit - val main = Java.run ”Hello”; [parsing Hello] [parsing java/lang/Object] [compiling java/lang/Object] [compiling Hello] [initializing java/lang/Object] [initializing Hello] val main = fn : string list -> unit - main [”World”]; Hello, World val it = () : unit - main []; uncaught exception ArrayIndexOutOfBounds raised at: Hello.main([Ljava/lang/String;)V - ˆD
  • 6. OO runtime ← functional languages Scala Clojure F etc.
  • 7. Patterns . Continuation-passing style . Format combinators . Nested data types eme Higher-order {functions, types}
  • 8. Pattern : Continuations A continuation is an argument that represents the rest of the computation meant to occur after the current function.
  • 9. Explicit continuations – straight-line def greeting [A] (name: String) (k: => A): A = printk(”Hello, ”) { printk(name) { printk(”!n”)(k) }} def printk [A] (s: String) (k: => A): A = { Console.print(s); k } scala> greeting(”Scala peeps”) { true } Hello, Scala peeps! res0: Boolean = true
  • 10. Pay it forward... Current function can ‘return’ a value by passing it as a parameter to its continuation.
  • 11. Explicit continuations – return values 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 test[A](k: String => A): A = plus(3,2) { a => times(3,2) { b => less(a,b) {k(”yes”)} {k(”no”)} }} scala> test{printk(_){}} yes
  • 12. Delimited continuations reset Serves as delimiter for CPS transformation. shift Captures current continuation as a function (up to dynamically-enclosing reset) then runs specified block instead.
  • 13. Delimited continuations def doSomething0 = reset { println(”Ready?”) val result = 1 + ˜˜˜˜˜˜˜˜ * 3 println(result) } ink of the rest of the computation as a function with the hole as its parameter.
  • 14. Delimited continuations def doSomething1 = reset { println(”Ready?”) val result = 1 + special * 3 println(result) } def special = shift { k: (Int => Unit) => println(99); ”Gotcha!” } shift captures continuation as k and then determines its own future.
  • 15. Delimited continuations def doSomething1 = reset { println(”Ready?”) val result = 1 + special * 3 println(result) } def special = shift { k: (Int => Unit) => println(99); ”Gotcha!” } scala> doSomething1 Ready? 99 res0: java.lang.String = Gotcha!
  • 16. Continuation-based user interaction def interact = reset { val a = ask(”Please give me a number”) val b = ask(”Please enter another number”) printf(”The sum of your numbers is: %dn”, a+b) } scala> interact Please give me a number answer using: submit(0xa9db9535, ...) scala> submit(0xa9db9535, 14) Please enter another number answer using: submit(0xbd1b3eb0, ...) scala> submit(0xbd1b3eb0, 28) The sum of your numbers is: 42
  • 17. Continuation-based user interaction val sessions = new HashMap[UUID, Int=>Unit] def ask(prompt: String): Int @cps[Unit] = shift { k: (Int => Unit) => { val id = uuidGen printf(”%snanswer using: submit(0x%x, ...)n”, prompt, id) sessions += id -> k }} def submit(id: UUID, data: Int) = sessions(id)(data) def interact = reset { val a = ask(”Please give me a number”) val b = ask(”Please enter another number”) printf(”The sum of your numbers is: %dn”, a+b) }
  • 18. Pattern : Format combinators [Danvy ] Typeful programmers covet printf. int a = 5; int b = 2; float c = a / (float) b; printf(”%d over %d is %.2fn”, a, b, c); Cannot type-check because format is just a string. What if it has structure, like abstract syntax tree?
  • 19. Typed format specifiers val frac: Int => Int => Float => String = d & ” over ” & d & ” is ” & f(2) & endl | val grade: Any => Double => Unit = ”Hello, ”&s&”: your exam score is ”&pct&endl |> val hex: (Int, Int, Int) => String = uncurried(”#”&x&x&x|) (Type annotations are for reference – not required.) scala> println(uncurried(frac)(a,b,c)) 5 over 2 is 2.50 scala> grade(”Joshua”)(0.97) Hello, Joshua: your exam score is 97% scala> println(”Roses are ”&s | hex(250, 21, 42)) Roses are #fa152a
  • 20. Buffer representation type Buf = List[String] def put(b: Buf, e: String): Buf = e :: b def finish(b: Buf): String = b.reverse.mkString def initial: Buf = Nil
  • 21. Operational semantics def lit(m:String)(k:Buf=>A)(b:Buf) = k(put(b,m)) def x(k:Buf=>A)(b:Buf)(i:Int) = k(put(b,i.toHexString)) def s(k:Buf=>A)(b:Buf)(o:Any) = k(put(b,o.toString)) (Not the actual implementation.) lit(”L”)(finish)(initial) ”L” x(finish)(initial)(42) ”2a” where: type Buf = List[String] def put(b: Buf, e: String): Buf = e :: b def finish(b: Buf): String = b.reverse.mkString def initial: Buf = Nil
  • 22. Function composition (lit(”L”) & x) (finish) (initial) (2815) lit(”L”)(x(finish)) (initial) (2815) lit(”L”)(λ b0.λ i.finish(i.toHex :: b0)) (initial) (2815) (λ b1.λ i.finish(i.toHex :: ”L” :: b1)) (initial) (2815) finish(2815.toHex :: ”L” :: initial) List(”aff”,”L”).reverse.mkString ”Laff” where: def lit(m:String)(k:Buf=>A)(b:Buf) = k(put(b,m)) def x(k:Buf=>A)(b:Buf)(i:Int) = k(put(b,i.toHexString)) def s(k:Buf=>A)(b:Buf)(o:Any) = k(put(b,o.toString))
  • 23. Combinator polymorphism What is the answer type? x: ∀A.(Buf => A) => Buf => Int => A finish: Buf => String x(x(x(finish))) A ≡ String A ≡ Int => String A ≡ Int => Int => String
  • 24. Type constructor polymorphism trait Compose[F[_],G[_]] { type T[X] = F[G[X]] } trait Fragment[F[_]] { def apply[A](k: Buf=>A): Buf=>F[A] def & [G[_]] (g: Fragment[G]) = new Fragment[Compose[F,G]#T] { def apply[A](k: Buf=>A) = Fragment.this(g(k)) } def | : F[String] = apply(finish(_))(initial) }
  • 25. Combinator implementations type Id[A] = A implicit def lit(s:String) = new Fragment[Id] { def apply[A](k: Cont[A]) = (b:Buf) => k(put(b,s)) } type IntF[A] = Int => A val x = new Fragment[IntF] { def apply[A](k: Cont[A]) = (b:Buf) => (i:Int) => k(put(b,i.toHexString)) }
  • 26. Pattern : Nested data types Usually, a polymorphic recursive data type is instantiated uniformly throughout: trait List[A] case class Nil[A]() extends List[A] case class Cons[A](hd:A, tl:List[A]) extends List[A] What if type parameter of recursive invocation differs?
  • 27. Weird examples trait Weird[A] case class Wil[A]() extends Weird[A] case class Wons[A](hd: A, tl: Weird[(A,A)]) extends Weird[A] // tail of Weird[A] is Weird[(A,A)] val z: Weird[Int] = Wons(1, Wil[I2]()) val y: Weird[Int] = Wons(1, Wons((2,3), Wil[I4])) val x: Weird[Int] = Wons( 1, Wons( (2,3), Wons( ((4,5),(6,7)), Wil[I8]()))) type I2 = (Int,Int) type I4 = (I2,I2) type I8 = (I4,I4)
  • 28. Square matrices [Okasaki ] Vector[Vector[A]] is a two-dimensional matrix of elements of type A. But lengths of rows (inner vectors) could differ. Using nested data types, recursively build a type constructor V[_] to represent a sequence of a fixed number of elements. en, Vector[V[A]] is a well-formed matrix, and V[V[A]] is square.
  • 29. Square matrix example scala> val m = tabulate(6){(i,j) => (i+1)*(j+1)} m: FastExpSquareMatrix.M[Int] = Even Odd Odd Zero (((),((((),(1,2)),((3,4),(5,6)) ),(((),(2,4)),((6,8),(10,12))))),(((((),(3,6)),(( 9,12),(15,18))),(((),(4,8)),((12,16),(20,24)))),( (((),(5,10)),((15,20),(25,30))),(((),(6,12)),((18 ,24),(30,36)))))) scala> val q = m(4,2) q: Int = 15 scala> val m2 = m updated (4,2,999) m2: FastExpSquareMatrix.M[Int] = Even Odd Odd Zero (((),((((),(1,2)),((3,4),(5,6)) ),(((),(2,4)),((6,8),(10,12))))),(((((),(3,6)),(( 9,12),(15,18))),(((),(4,8)),((12,16),(20,24)))),( (((),(5,10)),((999,20),(25,30))),(((),(6,12)),(( 18,24),(30,36))))))
  • 30. Analogy with fast exponentiation fastexp r b 0 = r fastexp r b n = fastexp r (b2 ) n/2 if n even fastexp r b n = fastexp (r · b) (b2 ) n/2 otherwise For example: fastexp 1 b 6 = Even fastexp 1 (b2 ) 3 = Odd 2 fastexp (1 · b2 ) (b2 ) 1 = Odd 2 22 fastexp (1 · b2 · b2 ) (b2 ) 0 = Zero 2 1 · b2 · b2
  • 31. Fast exponentiation of product types type U = Unit type I = Int fastExp U I 6 = // Even fastExp U (I,I) 3 = // Odd fastExp (U,(I,I)) ((I,I),(I,I)) 1 = // Odd fastExp ((U,(I,I)),((I,I),(I,I))) // Zero (((I,I),(I,I)),((I,I),(I,I))) 0 = ((U,(I,I)),((I,I),(I,I)))
  • 32. Implementation as nested data type trait Pr[V[_], W[_]] { type T[A] = (V[A],W[A]) } trait M [V[_],W[_],A] case class Zero [V[_],W[_],A] (data: V[V[A]]) extends M[V,W,A] case class Even [V[_],W[_],A] ( next: M[V, Pr[W,W]#T, A] ) extends M[V,W,A] case class Odd [V[_],W[_],A] ( next: M[Pr[V,W]#T, Pr[W,W]#T, A] ) extends M[V,W,A] type Empty[A] = Unit type Id[A] = A type Matrix[A] = M[Empty,Id,A]
  • 33. anks! [email protected] @chrisleague github.com/league/ slidesha.re/eREMXZ scala-fun-patterns Danvy, Olivier. “Functional Unparsing” J. Functional Programming (), . Okasaki, Chris. “From Fast Exponentiation to Square Matrices: An Adventure in Types” Int’l Conf. Functional Programming, .