SlideShare une entreprise Scribd logo
1  sur  147
Télécharger pour lire hors ligne
“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

Contenu connexe

Tendances

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
 

Tendances (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
 

Similaire à 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
 

Similaire à 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
 

Plus de 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
 

Plus de 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
 

Dernier

OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jNeo4j
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesVictoriaMetrics
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...OnePlan Solutions
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
Mastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxMastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxAS Design & AST.
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxRTS corp
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdfSteve Caron
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxRTS corp
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfmaor17
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdfAndrey Devyatkin
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITmanoharjgpsolutions
 

Dernier (20)

OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 Updates
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
Mastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxMastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptx
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptx
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdf
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh IT
 

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/