SlideShare a Scribd company logo
1 of 147
Download to read offline
“Going bananas with
recursion schemes for
fixed point data types”
Pawel Szulc
email: paul.szulc@gmail.com
twitter: @rabbitonweb
github: https://github.com/rabbitonweb/
Software
Engineering
Software engineering
“In late 1967 the Study Group recommended the holding of a
working conference on Software Engineering. The phrase
‘software engineering’ was deliberately chosen as being
provocative, in implying the need for software manufacture
to be based on the types of theoretical foundations and
practical disciplines, that are traditional in the established
branches of engineering.” [NATO68]
Elegance of Functional Programming
“Programming notation can be expressed by “formulæ and
equations (...) which share the elegance of those which
underlie physics and chemistry or any other branch of basic
science”. -- [BdM97]
Recursion
“Recursion is where Functional Programming hits
the bottom”
- Greg Pfeil
Recursion Schemes
“Functional Programming with Bananas, Lenses,
Envelopes and Barbed Wire” by Erik Meijer Maarten,
Maarten Fokkinga and Ross Paterson [MFP91]
Recursion Schemes
“Functional Programming with Bananas, Lenses,
Envelopes and Barbed Wire” by Erik Meijer Maarten,
Maarten Fokkinga and Ross Paterson [MFP91]
Describes:
● Simple, composable combinators (recursion schemes)
● Process of traversing recursive structures
Real world application
https://github.com/quasar-analytics/quasar
https://github.com/slamdata/matryoshka
Recursive Structures are common
Recursive Structures are common
● Simplest examples
○ List:
■ Cons(a, List)
■ Nil
○ Binary Tree
■ Node(a, Tree, Tree)
■ Leaf(a)
Recursive Structures are common
● Simplest examples
○ List:
■ Cons(a, List)
■ Nil
○ Binary Tree
■ Node(a, Tree, Tree)
■ Leaf(a)
● To name few examples:
○ File systems
○ 3D Graphics
○ Databases
Recursive Structures are common
● Simplest examples
○ List:
■ Cons(a, List)
■ Nil
○ Binary Tree
■ Node(a, Tree, Tree)
■ Leaf(a)
● To name few examples:
○ File systems
○ 3D Graphics
○ Databases
● Any nested, inductively defined type
Expressions!
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
Our example
102
+ 20.5 * 14.5
Expressions!
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
Our example
102
+ 20.5 * 14.5
Expressions!
Square (
Sum (
Square( IntValue(10) )
Multiply( DecValue(20.5),
DecValue(14.5) ),
)
)
Our example
(102
+ 20.5 * 14.5)2
Expressions!
Our example
(102
+ 20.5 * 14.5)2
Square
Sum
Square
10
Multiply
10 10
data Exp = IntVal Int |
DecVal Double |
Sum Exp Exp |
Multiply Exp Exp |
Divide Exp Exp |
Square Exp
data Exp = IntVal Int |
DecVal Double |
Sum Exp Exp |
Multiply Exp Exp |
Divide Exp Exp |
Square Exp
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
data Exp = IntVal Int |
DecVal Double |
Sum Exp Exp |
Multiply Exp Exp |
Divide Exp Exp |
Square Exp
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val evaluate: Exp => Double =
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2)
}
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val mkString: Exp => String = {
case IntValue(v) => v.toString
case DecValue(v) => v.toString
case Sum(exp1, exp2) => s"( ${mkStr(exp1)} + ${mkStr(exp2)})"
case Multiply(exp1, exp2) => s"( ${mkStr(exp1)} * ${mkStr(exp2)})"
case Square(exp) => s"(${mkStr(exp)})^2"
case Divide(exp1, exp2) => s"( ${mkStr(exp1)} / ${mkStr(exp2)})"
}
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val optimize: Exp => Exp = {
case Multiply(exp1, exp2)
if(exp1 == exp2) => Square(optimize(exp1))
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val optimize: Exp => Exp = {
case Multiply(exp1, exp2)
if(exp1 == exp2) => Square(optimize(exp1))
case IntValue(v) => IntValue(v)
case DecValue(v) => DecValue(v)
case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2))
case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2))
case Square(exp) => Square(optimize(exp))
case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2))
}
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val optimize: Exp => Exp = {
case Multiply(exp1, exp2)
if(exp1 == exp2) => Square(optimize(exp1))
case IntValue(v) => IntValue(v)
case DecValue(v) => DecValue(v)
case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2))
case Multiply(exp1, exp2) => Multiply(exp1, optimize(exp2))
case Square(exp) => Square(optimize(exp))
case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2))
}
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
val optimize: Exp => Exp = {
case Multiply(exp1, exp2)
if(exp1 == exp2) => Square(optimize(exp1))
case IntValue(v) => optimize(IntValue(v))
case DecValue(v) => optimize(DecValue(v))
case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2))
case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2))
case Square(exp) => Square(optimize(exp))
case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2))
}
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val mkString: Exp => String = {
case IntValue(v) => v.toString
case DecValue(v) => v.toString
case Sum(exp1, exp2) =>
s"(${mkStr(exp1)} + ${mkStr(exp2)})"
case Multiply(exp1, exp2) =>
s"(${mkStr(exp1)} * ${mkStr(exp2)})"
case Square(exp) =>
s"(${mkStr(exp)})^2"
case Divide(exp1, exp2) =>
s"( ${mkStr(exp1)} / ${mkStr(exp2)})"
} val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[?] =
Sum[?](IntValue[?](10),
IntValue[?](5))
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[?] =
Sum[?](IntValue[Unit](10),
IntValue[Unit](5))
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[?] =
Sum[?](IntValue[Unit](10),
IntValue[Unit](5))
)
Exp[Unit]
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[?] =
Sum[?](IntValue[Unit](10),
IntValue[Unit](5))
)
Exp[Unit]
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[?] =
Sum[?](IntValue[Unit](10),
IntValue[Unit](5))
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[?] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[?] =
Divide[?](
DecValue[?](5.2),
Sum[?](IntValue[?](10),
IntValue[?](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[?] =
Divide[?](
DecValue[?](5.2),
Sum[?](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[?] =
Divide[?](
DecValue[?](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[?] =
Divide[?](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[?] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp3: Exp = from(input)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
val exp3: Exp[?] = from(input)
sealed trait Exp[A]
final case class IntValue[A](v: Int) extends Exp[A]
final case class DecValue[A](v: Double) extends Exp[A]
final case class Sum[A](exp1: A, exp2: A) extends Exp[A]
final case class Multiply[A](exp1: A, exp2: A) extends Exp[A]
final case class Divide[A](exp1: A, exp2: A) extends Exp[A]
final case class Square[A](exp: A) extends Exp[A]
val exp1: Exp =
Sum(IntValue(10),
IntValue(5))
)
val exp2: Exp =
Divide(
DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
val exp3: Exp = from(input)
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](IntValue[Unit](10),
IntValue[Unit](5))
)
)
val exp3: Exp[Exp[Exp[Exp[Exp[Exp[Exp[Exp[Exp[Ex
Introducing:
fix point data
types!
Fix
case class Fix[F[_]](unFix: F[Fix[F]])
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](
IntValue[Unit](10),
IntValue[Unit](5)
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](
Fix(IntValue[Unit](10)),
Fix(IntValue[Unit](5))
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Exp[Exp[Unit]] =
Sum[Exp[Unit]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Exp[Exp[Unit]] =
Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Exp[Exp[Unit]] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](
IntValue[Unit](10),
IntValue[Unit](5))
)
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Exp[Unit]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
)
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
DecValue[Exp[Unit]](5.2),
Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
)
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
Fix(DecValue[Fix[Exp]](5.2)),
Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
)
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Exp[Exp[Exp[Unit]]] =
Divide[Exp[Exp[Unit]]](
Fix(DecValue[Fix[Exp]](5.2)),
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
))
)
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Exp[Exp[Exp[Unit]]] =
Fix(Divide[Fix[Exp]](
Fix(DecValue[Fix[Exp]](5.2)),
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Fix[Exp] =
Fix(Divide[Fix[Exp]](
Fix(DecValue[Fix[Exp]](5.2)),
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5))
))
val exp2: Fix[Exp] =
Fix(Divide[Fix[Exp]](
Fix(DecValue[Fix[Exp]](5.2)),
Fix(Sum[Fix[Exp]](
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](5)))
))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
val exp2: Fix[Exp] =
Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
val exp2: Fix[Exp] =
Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
val exp2: Fix[Exp] =
Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
case class Fix[F[_]](unFix: F[Fix[F]])
val exp1: Fix[Exp] =
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
val exp2: Fix[Exp] =
Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
val exp3: Fix[Exp] = from(input)
val evaluate: Exp => Double = {
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(exp1, exp2) =>
evaluate(exp1) + evaluate(exp2)
case Multiply(exp1, exp2) =>
evaluate(exp1) * evaluate(exp2)
case Square(exp) =>
val v = evaluate(exp)
v * v
case Divide(exp1, exp2) =>
evaluate(exp1) / evaluate(exp2)
}
val exp = Multiply(
Sum(IntValue(10),
DecValue(2.5)),
Divide(DecValue(5.2),
Sum(IntValue(10),
IntValue(5))
)
)
Multiply
Sum Divide
Int(10) Dec(2.5) Dec(5.2) Sum
Int(10) Int(5)
Need something
that will
traverse the
structure…
Catamorphism
greek κατα -“downwards” as in “catastrophe”
Missing Ingredients
1. Functor
2. Our Function
a. a thing that is actually doing stuff
Functor 101
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_], T](a: A[T])
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_], T](a: A[T])(trans: T => Int)
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_], T](a: A[T])(trans: T => Int): A[Int] = ???
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = ???
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = a.map(trans)
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = a.map(trans)
case class Container[T](t: T)
val r: Container[Int] =
foo[Container, String](Container("bar"))(str => str.length)
Functor 101
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = a.map(trans)
implicit val functor: Functor[Container] = new Functor[Container] {
def map[A, B](c: Container[A])(f: A => B): Container[B] = Container(f(c.t))
}
case class Container[T](t: T)
val r: Container[Int] =
foo[Container, String](Container("bar"))(str => str.length)
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
implicit val functor: Functor[Exp] = new Functor[Exp] {
def map[A, B](exp: Exp[A])(f: A => B): Exp[B] =
sealed trait Exp
final case class IntValue(v: Int) extends Exp
final case class DecValue(v: Double) extends Exp
final case class Sum(exp1: Exp, exp2: Exp) extends Exp
final case class Multiply(exp1: Exp, exp2: Exp) extends Exp
final case class Divide(exp1: Exp, exp2: Exp) extends Exp
final case class Square(exp: Exp) extends Exp
implicit val functor: Functor[Exp] = new Functor[Exp] {
def map[A, B](exp: Exp[A])(f: A => B): Exp[B] = exp match {
case Sum(a1, a2) => Sum(f(a1), f(a2))
case Multiply(a1, a2) => Multiply(f(a1), f(a2))
case Divide(a1, a2) => Divide(f(a1), f(a2))
case Square(a) => Square(f(a))
case IntValue(v) => IntValue(v)
case DecValue(v) => DecValue(v)
}
}
Missing Ingredients
1. Functor
2. Our Function
Missing Ingredients
1. Functor
2. Our Function
Missing Ingredients
1. Functor
2. F-Algebra
F-algebra
type Algebra[F[_], A] = F[A] => A
type Algebra[F[_], A] = F[A] => A
val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(a1, a2) => a1 + a2
case Multiply(a1, a2) => a1 * a2
case Square(a) => a * a
case Divide(a1, a2) => a1 / a2
}
type Algebra[F[_], A] = F[A] => A
val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(a1, a2) => a1 + a2
case Multiply(a1, a2) => a1 * a2
case Square(a) => a * a
case Divide(a1, a2) => a1 / a2
}
val mkStr: Algebra[Exp, String] = {
case IntValue(v) => v.toString
case DecValue(v) => v.toString
case Sum(a1, a2) => s"($a1 + $a2)"
case Multiply(a1, a2) => s"($a1 + $a2)"
case Square(a) => s"($a)^2"
case Divide(a1, a2) => s"($a1 + $a2)"
}
val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(a1, a2) => a1 + a2
case Multiply(a1, a2) => a1 * a2
case Square(a) => a * a
case Divide(a1, a2) => a1 / a2
}
val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(a1, a2) => a1 + a2
case Multiply(a1, a2) => a1 * a2
case Square(a) => a * a
case Divide(a1, a2) => a1 / a2
}
val exp2: Fix[Exp] = Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double
case IntValue(v) => v.toDouble
case DecValue(v) => v
case Sum(a1, a2) => a1 + a2
case Multiply(a1, a2) => a1 * a2
case Square(a) => a * a
case Divide(a1, a2) => a1 / a2
}
val exp2: Fix[Exp] = Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
> exp2.cata(evaluate)
0.3466666666666667
val mkStr: Algebra[Exp, String] = { // Exp[String] => String
case IntValue(v) => v.toString
case DecValue(v) => v.toString
case Sum(a1, a2) => s"($a1 + $a2)"
case Multiply(a1, a2) => s"($a1 + $a2)"
case Square(a) => s"($a)^2"
case Divide(a1, a2) => s"($a1 + $a2)"
}
val mkStr: Algebra[Exp, String] = { // Exp[String] => String
case IntValue(v) => v.toString
case DecValue(v) => v.toString
case Sum(a1, a2) => s"($a1 + $a2)"
case Multiply(a1, a2) => s"($a1 + $a2)"
case Square(a) => s"($a)^2"
case Divide(a1, a2) => s"($a1 + $a2)"
}
val exp2: Fix[Exp] = Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
val mkStr: Algebra[Exp, String] = { // Exp[String] => String
case IntValue(v) => v.toString
case DecValue(v) => v.toString
case Sum(a1, a2) => s"($a1 + $a2)"
case Multiply(a1, a2) => s"($a1 + $a2)"
case Square(a) => s"($a)^2"
case Divide(a1, a2) => s"($a1 + $a2)"
}
val exp2: Fix[Exp] = Fix(Divide(
Fix(DecValue(5.2)),
Fix(Sum(
Fix(IntValue(10)),
Fix(IntValue(5))
))
))
> exp2.cata(mkStr)
(5.2 + (10 + 5))
val optimize: Exp => Exp = {
case Multiply(exp1, exp2)
if(exp1 == exp2) => Square(optimize(exp1))
case IntValue(v) => IntValue(v)
case DecValue(v) => DecValue(v)
case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2))
case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2))
case Square(exp) => Square(optimize(exp))
case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2))
}
val optimize: Exp => Exp = {
case Multiply(exp1, exp2)
if(exp1 == exp2) => Square(optimize(exp1))
case IntValue(v) => IntValue(v)
case DecValue(v) => DecValue(v)
case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2))
case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2))
case Square(exp) => Square(optimize(exp))
case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2))
}
val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp]
case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1)))
case other => Fix(other)
}
val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp]
case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1)))
case other => Fix(other)
}
val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp]
case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1)))
case other => Fix(other)
}
val aTimesAExp: Fix[Exp] =
Fix(Multiply(
Fix(Sum(
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](20))
)),
Fix(Sum(
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](20))
))
))
val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp]
case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1)))
case other => Fix(other)
}
val aTimesAExp: Fix[Exp] =
Fix(Multiply(
Fix(Sum(
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](20))
)),
Fix(Sum(
Fix(IntValue[Fix[Exp]](10)),
Fix(IntValue[Fix[Exp]](20))
))
))
> aTimesAExp.cata(optimize)
Fix(Square(Fix(Sum(Fix(IntValue(10)),Fix(IntValue(20))))))
ZOO of
morphisims
anamorphism & hylomorphism
Anamorphism
● Constructs a structure from a value
Anamorphism
● Constructs a structure from a value
● Co- part of catamorphism
Anamorphism
● Constructs a structure from a value
● Co- part of catamorphism
● Instead of using Algebra[F[_], A] we will use Coalgebra[F[_], A]
Anamorphism
● Constructs a structure from a value
● Co- part of catamorphism
● Instead of using Algebra[F[_], A] we will use Coalgebra[F[_], A]
Example: given Int, construct expression called divisors that
● is multiplication of series of 2s & one odd value
● once evaluated will return initial Int
e.g 28 = 2 * 2 * 7
type Coalgebra[F[_], A] = A => F[A]
type Coalgebra[F[_], A] = A => F[A]
val divisors: Coalgebra[Exp, Int] = {
case n if(n % 2 == 0 && n != 2) => Multiply(2, n / 2)
case n => IntValue(n)
}
type Coalgebra[F[_], A] = A => F[A]
val divisors: Coalgebra[Exp, Int] = {
case n if(n % 2 == 0 && n != 2) => Multiply(2, n / 2)
case n => IntValue(n)
}
> 12.ana[Fix, Exp](divisors)
type Coalgebra[F[_], A] = A => F[A]
val divisors: Coalgebra[Exp, Int] = {
case n if(n % 2 == 0 && n != 2) => Multiply(2, n / 2)
case n => IntValue(n)
}
> 12.ana[Fix, Exp](divisors)
Fix(Multiply(Fix(IntValue(2)),Fix(Multiply(Fix(IntValue(2)),Fix(Multiply(Fix(IntVal
ue(2)),Fix(IntValue(7))))))))
Hylomorphism
Hylomorphism
● Constructs and then deconstructs a structure from a value
Hylomorphism
● Constructs and then deconstructs a structure from a value
● Anamorphism followed by catamorphism
Hylomorphism
● Constructs and then deconstructs a structure from a value
● Anamorphism followed by catamorphism
● Difference: evaluated in a single pass
Hylomorphism
● Constructs and then deconstructs a structure from a value
● Anamorphism followed by catamorphism
● Difference: evaluated in a single pass
value hylo value
ana cata
structure
Hylomorphism
● Constructs and then deconstructs a structure from a value
● Anamorphism followed by catamorphism
● Difference: evaluated in a single pass
value hylo value
ana cata
structure
val divisors: Coalgebra[Exp, Int] = { … } // Double => Exp[Double]
val evaluate: Algebra[Exp, Double] = { … } // Exp[Double] => Double
val divisors: Coalgebra[Exp, Int] = { … } // Double => Exp[Double]
val evaluate: Algebra[Exp, Double] = { … } // Exp[Double] => Double
describe("divisors") {
it("once evaluated will give initial value") {
forAll(positiveInt) { n =>
n.ana(divisiors).cata(evaluate) shouldEqual(n)
}
}
val divisors: Coalgebra[Exp, Int] = { … } // Double => Exp[Double]
val evaluate: Algebra[Exp, Double] = { … } // Exp[Double] => Double
describe("divisors") {
it("once evaluated will give initial value") {
forAll(positiveInt) { n =>
n.hylo(evaluate, divisors) shouldEqual(n)
}
}
What else?
To sum it up
● Recursion is hard, but it is ubiquitous
● Explicit recursion is tedious & error-prone
● Recursion schemas
○ set of composable combinators
○ well defined in both academia & industry
● Fix point data types
● You don’t have to do FP to take advantage of recursion schemes
● You can be famous! Build stuff!
References
[NATO68] - http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF
[MTEU16] - https://www.infoq.com/presentations/engineer-practices-techniques
[BdM97] - R. Bird and O. de Moor. Algebra of Programming. Series in Computer
Science. Prentice-Hall International, 1997. C.A.R. Hoare, series editor.
[MFP91] - http://eprints.eemcs.utwente.nl/7281/01/db-utwente-40501F46.pdf
[STOW14] - http://blog.sumtypeofway.com/an-introduction-to-recursion-schemes/
Pawel Szulc
Pawel Szulc
@rabbitonweb
Pawel Szulc
@rabbitonweb
paul.szulc@gmail.com
Pawel Szulc
@rabbitonweb
paul.szulc@gmail.com
http://rabbitonweb.com

More Related Content

What's hot

Declarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeDeclarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeKevlin Henney
 
Rcommands-for those who interested in R.
Rcommands-for those who interested in R.Rcommands-for those who interested in R.
Rcommands-for those who interested in R.Dr. Volkan OBAN
 
R reference card
R reference cardR reference card
R reference cardHesher Shih
 
Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3Khor SoonHin
 
Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2Khor SoonHin
 
Python легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиPython легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиMaxim Kulsha
 
Programming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYProgramming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYvikram mahendra
 
TensorFlow in Practice
TensorFlow in PracticeTensorFlow in Practice
TensorFlow in Practiceindico data
 
R short-refcard
R short-refcardR short-refcard
R short-refcardconline
 
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...Codemotion
 
Google Go For Ruby Hackers
Google Go For Ruby HackersGoogle Go For Ruby Hackers
Google Go For Ruby HackersEleanor McHugh
 
Gentlest Introduction to Tensorflow
Gentlest Introduction to TensorflowGentlest Introduction to Tensorflow
Gentlest Introduction to TensorflowKhor SoonHin
 

What's hot (16)

20170509 rand db_lesugent
20170509 rand db_lesugent20170509 rand db_lesugent
20170509 rand db_lesugent
 
Declarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeDeclarative Thinking, Declarative Practice
Declarative Thinking, Declarative Practice
 
Scala Parallel Collections
Scala Parallel CollectionsScala Parallel Collections
Scala Parallel Collections
 
Rcommands-for those who interested in R.
Rcommands-for those who interested in R.Rcommands-for those who interested in R.
Rcommands-for those who interested in R.
 
FYP Final Presentation
FYP Final PresentationFYP Final Presentation
FYP Final Presentation
 
R reference card
R reference cardR reference card
R reference card
 
Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3
 
Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2
 
R Refcard
R RefcardR Refcard
R Refcard
 
Python легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиPython легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачи
 
Programming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYProgramming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAY
 
TensorFlow in Practice
TensorFlow in PracticeTensorFlow in Practice
TensorFlow in Practice
 
R short-refcard
R short-refcardR short-refcard
R short-refcard
 
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
 
Google Go For Ruby Hackers
Google Go For Ruby HackersGoogle Go For Ruby Hackers
Google Go For Ruby Hackers
 
Gentlest Introduction to Tensorflow
Gentlest Introduction to TensorflowGentlest Introduction to Tensorflow
Gentlest Introduction to Tensorflow
 

Similar to Going bananas with recursion schemes for fixed point data types

Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
Compiler Construction | Lecture 5 | Transformation by Term Rewriting
Compiler Construction | Lecture 5 | Transformation by Term RewritingCompiler Construction | Lecture 5 | Transformation by Term Rewriting
Compiler Construction | Lecture 5 | Transformation by Term RewritingEelco Visser
 
Declare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term RewritingDeclare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term RewritingEelco Visser
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
ecoop-slides.pdf
ecoop-slides.pdfecoop-slides.pdf
ecoop-slides.pdfAndongFAN
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using ScalaSiarhiej Siemianchuk
 
Go Programming Language (Golang)
Go Programming Language (Golang)Go Programming Language (Golang)
Go Programming Language (Golang)Ishin Vin
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...Philip Schwarz
 
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
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...Philip Schwarz
 
ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うbpstudy
 
Scope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languagesScope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languagesEelco Visser
 
Futzing with actors (etc.)
Futzing with actors (etc.)Futzing with actors (etc.)
Futzing with actors (etc.)league
 
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingCS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingEelco Visser
 
Declare Your Language: Dynamic Semantics
Declare Your Language: Dynamic SemanticsDeclare Your Language: Dynamic Semantics
Declare Your Language: Dynamic SemanticsEelco Visser
 

Similar to Going bananas with recursion schemes for fixed point data types (20)

Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
Compiler Construction | Lecture 5 | Transformation by Term Rewriting
Compiler Construction | Lecture 5 | Transformation by Term RewritingCompiler Construction | Lecture 5 | Transformation by Term Rewriting
Compiler Construction | Lecture 5 | Transformation by Term Rewriting
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Declare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term RewritingDeclare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term Rewriting
 
Term Rewriting
Term RewritingTerm Rewriting
Term Rewriting
 
Monadologie
MonadologieMonadologie
Monadologie
 
Alastair Butler - 2015 - Round trips with meaning stopovers
Alastair Butler - 2015 - Round trips with meaning stopoversAlastair Butler - 2015 - Round trips with meaning stopovers
Alastair Butler - 2015 - Round trips with meaning stopovers
 
ecoop-slides.pdf
ecoop-slides.pdfecoop-slides.pdf
ecoop-slides.pdf
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using Scala
 
Go Programming Language (Golang)
Go Programming Language (Golang)Go Programming Language (Golang)
Go Programming Language (Golang)
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
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
 
Interpreter Case Study - Design Patterns
Interpreter Case Study - Design PatternsInterpreter Case Study - Design Patterns
Interpreter Case Study - Design Patterns
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
Scala Paradigms
Scala ParadigmsScala Paradigms
Scala Paradigms
 
ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使う
 
Scope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languagesScope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languages
 
Futzing with actors (etc.)
Futzing with actors (etc.)Futzing with actors (etc.)
Futzing with actors (etc.)
 
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingCS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
 
Declare Your Language: Dynamic Semantics
Declare Your Language: Dynamic SemanticsDeclare Your Language: Dynamic Semantics
Declare Your Language: Dynamic Semantics
 

More from Pawel Szulc

Getting acquainted with Lens
Getting acquainted with LensGetting acquainted with Lens
Getting acquainted with LensPawel Szulc
 
Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Pawel Szulc
 
Painless Haskell
Painless HaskellPainless Haskell
Painless HaskellPawel Szulc
 
Trip with monads
Trip with monadsTrip with monads
Trip with monadsPawel Szulc
 
Trip with monads
Trip with monadsTrip with monads
Trip with monadsPawel Szulc
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineersPawel Szulc
 
RChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiRChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiPawel Szulc
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineersPawel Szulc
 
Understanding distributed calculi in Haskell
Understanding distributed calculi in HaskellUnderstanding distributed calculi in Haskell
Understanding distributed calculi in HaskellPawel Szulc
 
Software engineering the genesis
Software engineering  the genesisSoftware engineering  the genesis
Software engineering the genesisPawel Szulc
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs FreePawel Szulc
 
Writing your own RDD for fun and profit
Writing your own RDD for fun and profitWriting your own RDD for fun and profit
Writing your own RDD for fun and profitPawel Szulc
 
The cats toolbox a quick tour of some basic typeclasses
The cats toolbox  a quick tour of some basic typeclassesThe cats toolbox  a quick tour of some basic typeclasses
The cats toolbox a quick tour of some basic typeclassesPawel Szulc
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classesPawel Szulc
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenPawel Szulc
 
Apache spark workshop
Apache spark workshopApache spark workshop
Apache spark workshopPawel Szulc
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 minPawel Szulc
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygookPawel Szulc
 
Apache spark when things go wrong
Apache spark   when things go wrongApache spark   when things go wrong
Apache spark when things go wrongPawel Szulc
 

More from Pawel Szulc (20)

Getting acquainted with Lens
Getting acquainted with LensGetting acquainted with Lens
Getting acquainted with Lens
 
Impossibility
ImpossibilityImpossibility
Impossibility
 
Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)
 
Painless Haskell
Painless HaskellPainless Haskell
Painless Haskell
 
Trip with monads
Trip with monadsTrip with monads
Trip with monads
 
Trip with monads
Trip with monadsTrip with monads
Trip with monads
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineers
 
RChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiRChain - Understanding Distributed Calculi
RChain - Understanding Distributed Calculi
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineers
 
Understanding distributed calculi in Haskell
Understanding distributed calculi in HaskellUnderstanding distributed calculi in Haskell
Understanding distributed calculi in Haskell
 
Software engineering the genesis
Software engineering  the genesisSoftware engineering  the genesis
Software engineering the genesis
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs Free
 
Writing your own RDD for fun and profit
Writing your own RDD for fun and profitWriting your own RDD for fun and profit
Writing your own RDD for fun and profit
 
The cats toolbox a quick tour of some basic typeclasses
The cats toolbox  a quick tour of some basic typeclassesThe cats toolbox  a quick tour of some basic typeclasses
The cats toolbox a quick tour of some basic typeclasses
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heaven
 
Apache spark workshop
Apache spark workshopApache spark workshop
Apache spark workshop
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
 
Apache spark when things go wrong
Apache spark   when things go wrongApache spark   when things go wrong
Apache spark when things go wrong
 

Recently uploaded

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 

Recently uploaded (20)

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 

Going bananas with recursion schemes for fixed point data types

  • 1. “Going bananas with recursion schemes for fixed point data types” Pawel Szulc email: paul.szulc@gmail.com twitter: @rabbitonweb github: https://github.com/rabbitonweb/
  • 3. Software engineering “In late 1967 the Study Group recommended the holding of a working conference on Software Engineering. The phrase ‘software engineering’ was deliberately chosen as being provocative, in implying the need for software manufacture to be based on the types of theoretical foundations and practical disciplines, that are traditional in the established branches of engineering.” [NATO68]
  • 4. Elegance of Functional Programming “Programming notation can be expressed by “formulæ and equations (...) which share the elegance of those which underlie physics and chemistry or any other branch of basic science”. -- [BdM97]
  • 5. Recursion “Recursion is where Functional Programming hits the bottom” - Greg Pfeil
  • 6. Recursion Schemes “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire” by Erik Meijer Maarten, Maarten Fokkinga and Ross Paterson [MFP91]
  • 7. Recursion Schemes “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire” by Erik Meijer Maarten, Maarten Fokkinga and Ross Paterson [MFP91] Describes: ● Simple, composable combinators (recursion schemes) ● Process of traversing recursive structures
  • 10. Recursive Structures are common ● Simplest examples ○ List: ■ Cons(a, List) ■ Nil ○ Binary Tree ■ Node(a, Tree, Tree) ■ Leaf(a)
  • 11. Recursive Structures are common ● Simplest examples ○ List: ■ Cons(a, List) ■ Nil ○ Binary Tree ■ Node(a, Tree, Tree) ■ Leaf(a) ● To name few examples: ○ File systems ○ 3D Graphics ○ Databases
  • 12. Recursive Structures are common ● Simplest examples ○ List: ■ Cons(a, List) ■ Nil ○ Binary Tree ■ Node(a, Tree, Tree) ■ Leaf(a) ● To name few examples: ○ File systems ○ 3D Graphics ○ Databases ● Any nested, inductively defined type
  • 14. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) Our example 102 + 20.5 * 14.5
  • 15. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) Our example 102 + 20.5 * 14.5
  • 16. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) Our example 102 + 20.5 * 14.5
  • 17. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) Our example 102 + 20.5 * 14.5
  • 18. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) Our example 102 + 20.5 * 14.5
  • 19. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), Our example 102 + 20.5 * 14.5
  • 20. Expressions! Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) Our example 102 + 20.5 * 14.5
  • 21. Expressions! Square ( Sum ( Square( IntValue(10) ) Multiply( DecValue(20.5), DecValue(14.5) ), ) ) Our example (102 + 20.5 * 14.5)2
  • 22. Expressions! Our example (102 + 20.5 * 14.5)2 Square Sum Square 10 Multiply 10 10
  • 23. data Exp = IntVal Int | DecVal Double | Sum Exp Exp | Multiply Exp Exp | Divide Exp Exp | Square Exp
  • 24. data Exp = IntVal Int | DecVal Double | Sum Exp Exp | Multiply Exp Exp | Divide Exp Exp | Square Exp sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp
  • 25. data Exp = IntVal Int | DecVal Double | Sum Exp Exp | Multiply Exp Exp | Divide Exp Exp | Square Exp sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp
  • 26. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val evaluate: Exp => Double =
  • 27. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) }
  • 28. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val mkString: Exp => String = { case IntValue(v) => v.toString case DecValue(v) => v.toString case Sum(exp1, exp2) => s"( ${mkStr(exp1)} + ${mkStr(exp2)})" case Multiply(exp1, exp2) => s"( ${mkStr(exp1)} * ${mkStr(exp2)})" case Square(exp) => s"(${mkStr(exp)})^2" case Divide(exp1, exp2) => s"( ${mkStr(exp1)} / ${mkStr(exp2)})" }
  • 29. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val optimize: Exp => Exp = { case Multiply(exp1, exp2) if(exp1 == exp2) => Square(optimize(exp1))
  • 30. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val optimize: Exp => Exp = { case Multiply(exp1, exp2) if(exp1 == exp2) => Square(optimize(exp1)) case IntValue(v) => IntValue(v) case DecValue(v) => DecValue(v) case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2)) case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2)) case Square(exp) => Square(optimize(exp)) case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2)) }
  • 31. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val optimize: Exp => Exp = { case Multiply(exp1, exp2) if(exp1 == exp2) => Square(optimize(exp1)) case IntValue(v) => IntValue(v) case DecValue(v) => DecValue(v) case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2)) case Multiply(exp1, exp2) => Multiply(exp1, optimize(exp2)) case Square(exp) => Square(optimize(exp)) case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2)) }
  • 32. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp val optimize: Exp => Exp = { case Multiply(exp1, exp2) if(exp1 == exp2) => Square(optimize(exp1)) case IntValue(v) => optimize(IntValue(v)) case DecValue(v) => optimize(DecValue(v)) case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2)) case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2)) case Square(exp) => Square(optimize(exp)) case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2)) }
  • 33. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 34. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 35. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 36. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 37. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 38. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 39. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 40. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 41. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 42. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 43. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 44. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 45. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 46. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 47. val mkString: Exp => String = { case IntValue(v) => v.toString case DecValue(v) => v.toString case Sum(exp1, exp2) => s"(${mkStr(exp1)} + ${mkStr(exp2)})" case Multiply(exp1, exp2) => s"(${mkStr(exp1)} * ${mkStr(exp2)})" case Square(exp) => s"(${mkStr(exp)})^2" case Divide(exp1, exp2) => s"( ${mkStr(exp1)} / ${mkStr(exp2)})" } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 48. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 49. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp
  • 50. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A]
  • 51. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[?] = Sum[?](IntValue[?](10), IntValue[?](5)) )
  • 52. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[?] = Sum[?](IntValue[Unit](10), IntValue[Unit](5)) )
  • 53. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[?] = Sum[?](IntValue[Unit](10), IntValue[Unit](5)) ) Exp[Unit]
  • 54. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[?] = Sum[?](IntValue[Unit](10), IntValue[Unit](5)) ) Exp[Unit]
  • 55. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[?] = Sum[?](IntValue[Unit](10), IntValue[Unit](5)) )
  • 56. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[?] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) )
  • 57. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) )
  • 58. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[?] = Divide[?]( DecValue[?](5.2), Sum[?](IntValue[?](10), IntValue[?](5)) ) )
  • 59. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[?] = Divide[?]( DecValue[?](5.2), Sum[?](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 60. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[?] = Divide[?]( DecValue[?](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 61. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[?] = Divide[?]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 62. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[?] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 63. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 64. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 65. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 66. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp3: Exp = from(input) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) ) val exp3: Exp[?] = from(input)
  • 67. sealed trait Exp[A] final case class IntValue[A](v: Int) extends Exp[A] final case class DecValue[A](v: Double) extends Exp[A] final case class Sum[A](exp1: A, exp2: A) extends Exp[A] final case class Multiply[A](exp1: A, exp2: A) extends Exp[A] final case class Divide[A](exp1: A, exp2: A) extends Exp[A] final case class Square[A](exp: A) extends Exp[A] val exp1: Exp = Sum(IntValue(10), IntValue(5)) ) val exp2: Exp = Divide( DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) val exp3: Exp = from(input) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]](IntValue[Unit](10), IntValue[Unit](5)) ) ) val exp3: Exp[Exp[Exp[Exp[Exp[Exp[Exp[Exp[Exp[Ex
  • 69. Fix
  • 70.
  • 72. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]]( IntValue[Unit](10), IntValue[Unit](5) )
  • 73. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]]( Fix(IntValue[Unit](10)), Fix(IntValue[Unit](5)) )
  • 74. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Exp[Exp[Unit]] = Sum[Exp[Unit]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )
  • 75. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Exp[Exp[Unit]] = Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )
  • 76. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Exp[Exp[Unit]] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) ))
  • 77. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) ))
  • 78. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]]( IntValue[Unit](10), IntValue[Unit](5)) ) )
  • 79. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Exp[Unit]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) ) )
  • 80. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( DecValue[Exp[Unit]](5.2), Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) ) )
  • 81. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( Fix(DecValue[Fix[Exp]](5.2)), Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) ) )
  • 82. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Exp[Exp[Exp[Unit]]] = Divide[Exp[Exp[Unit]]]( Fix(DecValue[Fix[Exp]](5.2)), Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) )) )
  • 83. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Exp[Exp[Exp[Unit]]] = Fix(Divide[Fix[Exp]]( Fix(DecValue[Fix[Exp]](5.2)), Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) )) ))
  • 84. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Fix[Exp] = Fix(Divide[Fix[Exp]]( Fix(DecValue[Fix[Exp]](5.2)), Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) )) ))
  • 85. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5)) )) val exp2: Fix[Exp] = Fix(Divide[Fix[Exp]]( Fix(DecValue[Fix[Exp]](5.2)), Fix(Sum[Fix[Exp]]( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](5))) )) ))
  • 86. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) ))
  • 87. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) ))
  • 88. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) ))
  • 89. case class Fix[F[_]](unFix: F[Fix[F]]) val exp1: Fix[Exp] = Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) )) val exp3: Fix[Exp] = from(input)
  • 90. val evaluate: Exp => Double = { case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(exp1, exp2) => evaluate(exp1) + evaluate(exp2) case Multiply(exp1, exp2) => evaluate(exp1) * evaluate(exp2) case Square(exp) => val v = evaluate(exp) v * v case Divide(exp1, exp2) => evaluate(exp1) / evaluate(exp2) } val exp = Multiply( Sum(IntValue(10), DecValue(2.5)), Divide(DecValue(5.2), Sum(IntValue(10), IntValue(5)) ) ) Multiply Sum Divide Int(10) Dec(2.5) Dec(5.2) Sum Int(10) Int(5)
  • 93.
  • 94. Missing Ingredients 1. Functor 2. Our Function a. a thing that is actually doing stuff
  • 96. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] }
  • 97. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_], T](a: A[T])
  • 98. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_], T](a: A[T])(trans: T => Int)
  • 99. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_], T](a: A[T])(trans: T => Int): A[Int] = ???
  • 100. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = ???
  • 101. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = a.map(trans)
  • 102. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = a.map(trans) case class Container[T](t: T) val r: Container[Int] = foo[Container, String](Container("bar"))(str => str.length)
  • 103. Functor 101 trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } def foo[A[_] : Functor, T](a: A[T])(trans: T => Int): A[Int] = a.map(trans) implicit val functor: Functor[Container] = new Functor[Container] { def map[A, B](c: Container[A])(f: A => B): Container[B] = Container(f(c.t)) } case class Container[T](t: T) val r: Container[Int] = foo[Container, String](Container("bar"))(str => str.length)
  • 104. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp implicit val functor: Functor[Exp] = new Functor[Exp] { def map[A, B](exp: Exp[A])(f: A => B): Exp[B] =
  • 105. sealed trait Exp final case class IntValue(v: Int) extends Exp final case class DecValue(v: Double) extends Exp final case class Sum(exp1: Exp, exp2: Exp) extends Exp final case class Multiply(exp1: Exp, exp2: Exp) extends Exp final case class Divide(exp1: Exp, exp2: Exp) extends Exp final case class Square(exp: Exp) extends Exp implicit val functor: Functor[Exp] = new Functor[Exp] { def map[A, B](exp: Exp[A])(f: A => B): Exp[B] = exp match { case Sum(a1, a2) => Sum(f(a1), f(a2)) case Multiply(a1, a2) => Multiply(f(a1), f(a2)) case Divide(a1, a2) => Divide(f(a1), f(a2)) case Square(a) => Square(f(a)) case IntValue(v) => IntValue(v) case DecValue(v) => DecValue(v) } }
  • 110. type Algebra[F[_], A] = F[A] => A val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(a1, a2) => a1 + a2 case Multiply(a1, a2) => a1 * a2 case Square(a) => a * a case Divide(a1, a2) => a1 / a2 }
  • 111. type Algebra[F[_], A] = F[A] => A val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(a1, a2) => a1 + a2 case Multiply(a1, a2) => a1 * a2 case Square(a) => a * a case Divide(a1, a2) => a1 / a2 } val mkStr: Algebra[Exp, String] = { case IntValue(v) => v.toString case DecValue(v) => v.toString case Sum(a1, a2) => s"($a1 + $a2)" case Multiply(a1, a2) => s"($a1 + $a2)" case Square(a) => s"($a)^2" case Divide(a1, a2) => s"($a1 + $a2)" }
  • 112. val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(a1, a2) => a1 + a2 case Multiply(a1, a2) => a1 * a2 case Square(a) => a * a case Divide(a1, a2) => a1 / a2 }
  • 113. val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(a1, a2) => a1 + a2 case Multiply(a1, a2) => a1 * a2 case Square(a) => a * a case Divide(a1, a2) => a1 / a2 } val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) ))
  • 114. val evaluate: Algebra[Exp, Double] = { // Exp[Double] => Double case IntValue(v) => v.toDouble case DecValue(v) => v case Sum(a1, a2) => a1 + a2 case Multiply(a1, a2) => a1 * a2 case Square(a) => a * a case Divide(a1, a2) => a1 / a2 } val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) )) > exp2.cata(evaluate) 0.3466666666666667
  • 115. val mkStr: Algebra[Exp, String] = { // Exp[String] => String case IntValue(v) => v.toString case DecValue(v) => v.toString case Sum(a1, a2) => s"($a1 + $a2)" case Multiply(a1, a2) => s"($a1 + $a2)" case Square(a) => s"($a)^2" case Divide(a1, a2) => s"($a1 + $a2)" }
  • 116. val mkStr: Algebra[Exp, String] = { // Exp[String] => String case IntValue(v) => v.toString case DecValue(v) => v.toString case Sum(a1, a2) => s"($a1 + $a2)" case Multiply(a1, a2) => s"($a1 + $a2)" case Square(a) => s"($a)^2" case Divide(a1, a2) => s"($a1 + $a2)" } val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) ))
  • 117. val mkStr: Algebra[Exp, String] = { // Exp[String] => String case IntValue(v) => v.toString case DecValue(v) => v.toString case Sum(a1, a2) => s"($a1 + $a2)" case Multiply(a1, a2) => s"($a1 + $a2)" case Square(a) => s"($a)^2" case Divide(a1, a2) => s"($a1 + $a2)" } val exp2: Fix[Exp] = Fix(Divide( Fix(DecValue(5.2)), Fix(Sum( Fix(IntValue(10)), Fix(IntValue(5)) )) )) > exp2.cata(mkStr) (5.2 + (10 + 5))
  • 118. val optimize: Exp => Exp = { case Multiply(exp1, exp2) if(exp1 == exp2) => Square(optimize(exp1)) case IntValue(v) => IntValue(v) case DecValue(v) => DecValue(v) case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2)) case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2)) case Square(exp) => Square(optimize(exp)) case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2)) }
  • 119. val optimize: Exp => Exp = { case Multiply(exp1, exp2) if(exp1 == exp2) => Square(optimize(exp1)) case IntValue(v) => IntValue(v) case DecValue(v) => DecValue(v) case Sum(exp1, exp2) => Sum(optimize(exp1), optimize(exp2)) case Multiply(exp1, exp2) => Multiply(optimize(exp1), optimize(exp2)) case Square(exp) => Square(optimize(exp)) case Divide(exp1, exp2) => Divide(optimize(exp1), optimize(exp2)) } val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp] case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1))) case other => Fix(other) }
  • 120. val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp] case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1))) case other => Fix(other) }
  • 121. val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp] case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1))) case other => Fix(other) } val aTimesAExp: Fix[Exp] = Fix(Multiply( Fix(Sum( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](20)) )), Fix(Sum( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](20)) )) ))
  • 122. val optimize: Algebra[Exp, Fix[Exp]] = { // Exp[Fix[Exp]] => Fix[Exp] case Multiply(Fix(a1), Fix(a2)) if(a1 == a2) => Fix(Square(Fix(a1))) case other => Fix(other) } val aTimesAExp: Fix[Exp] = Fix(Multiply( Fix(Sum( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](20)) )), Fix(Sum( Fix(IntValue[Fix[Exp]](10)), Fix(IntValue[Fix[Exp]](20)) )) )) > aTimesAExp.cata(optimize) Fix(Square(Fix(Sum(Fix(IntValue(10)),Fix(IntValue(20))))))
  • 124. Anamorphism ● Constructs a structure from a value
  • 125. Anamorphism ● Constructs a structure from a value ● Co- part of catamorphism
  • 126. Anamorphism ● Constructs a structure from a value ● Co- part of catamorphism ● Instead of using Algebra[F[_], A] we will use Coalgebra[F[_], A]
  • 127. Anamorphism ● Constructs a structure from a value ● Co- part of catamorphism ● Instead of using Algebra[F[_], A] we will use Coalgebra[F[_], A] Example: given Int, construct expression called divisors that ● is multiplication of series of 2s & one odd value ● once evaluated will return initial Int e.g 28 = 2 * 2 * 7
  • 128. type Coalgebra[F[_], A] = A => F[A]
  • 129. type Coalgebra[F[_], A] = A => F[A] val divisors: Coalgebra[Exp, Int] = { case n if(n % 2 == 0 && n != 2) => Multiply(2, n / 2) case n => IntValue(n) }
  • 130. type Coalgebra[F[_], A] = A => F[A] val divisors: Coalgebra[Exp, Int] = { case n if(n % 2 == 0 && n != 2) => Multiply(2, n / 2) case n => IntValue(n) } > 12.ana[Fix, Exp](divisors)
  • 131. type Coalgebra[F[_], A] = A => F[A] val divisors: Coalgebra[Exp, Int] = { case n if(n % 2 == 0 && n != 2) => Multiply(2, n / 2) case n => IntValue(n) } > 12.ana[Fix, Exp](divisors) Fix(Multiply(Fix(IntValue(2)),Fix(Multiply(Fix(IntValue(2)),Fix(Multiply(Fix(IntVal ue(2)),Fix(IntValue(7))))))))
  • 133. Hylomorphism ● Constructs and then deconstructs a structure from a value
  • 134. Hylomorphism ● Constructs and then deconstructs a structure from a value ● Anamorphism followed by catamorphism
  • 135. Hylomorphism ● Constructs and then deconstructs a structure from a value ● Anamorphism followed by catamorphism ● Difference: evaluated in a single pass
  • 136. Hylomorphism ● Constructs and then deconstructs a structure from a value ● Anamorphism followed by catamorphism ● Difference: evaluated in a single pass value hylo value ana cata structure
  • 137. Hylomorphism ● Constructs and then deconstructs a structure from a value ● Anamorphism followed by catamorphism ● Difference: evaluated in a single pass value hylo value ana cata structure
  • 138. val divisors: Coalgebra[Exp, Int] = { … } // Double => Exp[Double] val evaluate: Algebra[Exp, Double] = { … } // Exp[Double] => Double
  • 139. val divisors: Coalgebra[Exp, Int] = { … } // Double => Exp[Double] val evaluate: Algebra[Exp, Double] = { … } // Exp[Double] => Double describe("divisors") { it("once evaluated will give initial value") { forAll(positiveInt) { n => n.ana(divisiors).cata(evaluate) shouldEqual(n) } }
  • 140. val divisors: Coalgebra[Exp, Int] = { … } // Double => Exp[Double] val evaluate: Algebra[Exp, Double] = { … } // Exp[Double] => Double describe("divisors") { it("once evaluated will give initial value") { forAll(positiveInt) { n => n.hylo(evaluate, divisors) shouldEqual(n) } }
  • 142. To sum it up ● Recursion is hard, but it is ubiquitous ● Explicit recursion is tedious & error-prone ● Recursion schemas ○ set of composable combinators ○ well defined in both academia & industry ● Fix point data types ● You don’t have to do FP to take advantage of recursion schemes ● You can be famous! Build stuff!
  • 143. References [NATO68] - http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF [MTEU16] - https://www.infoq.com/presentations/engineer-practices-techniques [BdM97] - R. Bird and O. de Moor. Algebra of Programming. Series in Computer Science. Prentice-Hall International, 1997. C.A.R. Hoare, series editor. [MFP91] - http://eprints.eemcs.utwente.nl/7281/01/db-utwente-40501F46.pdf [STOW14] - http://blog.sumtypeofway.com/an-introduction-to-recursion-schemes/