Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Recursion
schemes
in Scala
and also fixed point data types
Today we will speak about freaky
functional stuff, enjoy :)
Arthur Kushka // @Arhelmus
Yo
a method for structuring programs mainly
as sequences of possibly nested function
procedure calls.
programmingFunctional
(...
everywhere!
Recursive schemas
Lists and trees
Filesystems
Databases
list match {
   // Cons(1, Cons(2, Cons(3, Nil)))
   c...
Example
01
Sum
Multiply
Divide
Square
Math equasionevaluation
Lets define our DSL
sealed trait Exp
case class IntValue(value: Int) extends Exp
case class DecValue(value: Double) extend...
Example
equation
Sum(
   Square(
     IntValue(4)
   ),
   Multiply(
     DecValue(3.3),
     IntValue(4)
   )
 )
4^2 + 3....
val evaluate: Exp => Double = {
   case DecValue(value) => value
   case IntValue(value) => value.toDouble
   case Sum(exp...
val stringify: Exp => String = {
   case DecValue(value) => value.toString
   case IntValue(value) => value.toString
   ca...
It will work!
but...
evaluate(expression) // prints 29.2
stringify(expression) // prints 4 ^ 2 + 3.3 * 4
There are a lot of
mess
   case Sum(exp1: Exp, exp2: Exp) =>
      evaluate(exp1) + evaluate(exp2)
And not only...
Problem of partial
interpretation
val optimize: Exp => Exp = {
   case Multiply(exp1, exp2) if exp1 == exp2 =>
     Square...
going to
result
types02
Generalize it
sealed trait Exp[T]
case class IntValue[T](value: Int) extends Exp[T]
case class DecValue[T](value: Double) ...
val expression: Exp[Exp[Exp[Unit]]] =
Sum[Exp[Exp[Unit]]](
   Square[Exp[Unit]](
     IntValue[Unit](4)
   ),
   Multiply[...
its like a hiding of part that doesn't matter
fixed point types
F[_] is a generic type with a hole, after
wrapping of Exp with that we will have
Fix[Exp] type.
let's add
typehack
case cl...
val expression: Fix[Exp] = Fix(Sum(
   Fix(Square(
     Fix(IntValue(4))
   )),
   Fix(Multiply(
     Fix(DecValue(3.3)),
...
case class Square[T](exp: T) extends Exp[T]
object Square {
  def apply(fixExp: Exp[Fix[Exp]]) = Fix[Exp](fixExp)
}
val ex...
time to traverse
our structure
03
def map[F[_], A, B](fa: F[A])(f: A=>B): F[B]
Functor 911
Scalaz example
case class Container[T](data: T)
implicit val functor = new Functor[Container] {
override def map[A, B](fa:...
implicit val functor = new Functor[Exp] {
override def map[A, B](fa: Exp[A])(f: A => B): Exp[B] =
fa match {
case IntValue...
catamorphism
anamorphism
hylomorphism04
“Functional Programming with Bananas,
Lenses, Envelopes and Barbed Wire”, by
Erik Meijer
generalized folding operation
cat...
Lets define
Algebra
type Algebra[F[_], A] = F[A] => A
val evaluate: Algebra[Exp, Double] = {
   case IntValue(v) => v.toDo...
So as a result
val expression: Fix[Exp] = Sum(
   Multiply(IntValue(4), IntValue(4)),
   Multiply(DecValue(3.3), IntValue(...
do you remember about partial interpretation?
Extra profit
val optimize: Algebra[Exp, Fix[Exp]] = {
   case Multiply(Fix(e...
val evaluate: Exp => Double = {
   case DecValue(value) => value
   case IntValue(value) => value.toDouble
   case Sum(exp...
catamorphism: F[_] => A 
anamorphism: A => F[_] 
hylomorphism: F[_] => A => F[_] 
Just good to
know
Fixed point types is perfect to create
DSLs
Recursion schemas is composable
All you need to use that stuff, you
already kn...
thank you.
any questions?
Prochain SlideShare
Chargement dans…5
×

Recursion schemes in Scala

966 vues

Publié le

Talk that describes basics of recursion schemes and fixed data types in Scala.

Publié dans : Ingénierie
  • Soyez le premier à commenter

Recursion schemes in Scala

  1. 1. Recursion schemes in Scala and also fixed point data types
  2. 2. Today we will speak about freaky functional stuff, enjoy :) Arthur Kushka // @Arhelmus Yo
  3. 3. a method for structuring programs mainly as sequences of possibly nested function procedure calls. programmingFunctional ((x: Array[Byte]) => x)    .andThen(encodeBase64)    .andThen(name => s"Hello $name")    .andThen(println)
  4. 4. everywhere! Recursive schemas Lists and trees Filesystems Databases list match {    // Cons(1, Cons(2, Cons(3, Nil)))    case 1 :: 2 :: 3 :: Nil =>    case Nil =>  }
  5. 5. Example 01
  6. 6. Sum Multiply Divide Square Math equasionevaluation
  7. 7. Lets define our DSL sealed trait Exp case class IntValue(value: Int) extends Exp case class DecValue(value: Double) extends Exp case class Sum(exp1: Exp, exp2: Exp) extends Exp case class Multiply(exp1: Exp, exp2: Exp) extends Exp case class Divide(exp1: Exp, exp2: Exp) extends Exp case class Square(exp: Exp) extends Exp
  8. 8. Example equation Sum(    Square(      IntValue(4)    ),    Multiply(      DecValue(3.3),      IntValue(4)    )  ) 4^2 + 3.3 * 4
  9. 9. val evaluate: Exp => Double = {    case DecValue(value) => value    case IntValue(value) => value.toDouble    case Sum(exp1, exp2) =>       evaluate(exp1) + evaluate(exp2)    case Multiply(exp1, exp2) =>       evaluate(exp1) * evaluate(exp2)    case Divide(exp1, exp2) =>       evaluate(exp1) / evaluate(exp2)    case Square(exp) =>      val v = evaluate(exp)      v * v  }
  10. 10. val stringify: Exp => String = {    case DecValue(value) => value.toString    case IntValue(value) => value.toString    case Sum(exp1, exp2) =>      s"${stringify(exp1)} + ${stringify(exp2)}"    case Square(exp) =>      s"${stringify(exp)} ^ 2"    case Multiply(exp1, exp2) =>      s"${stringify(exp1)} * ${stringify(exp2)}"    case Divide(exp1, exp2) =>      s"${stringify(exp1)} / ${stringify(exp2)}"  }
  11. 11. It will work! but... evaluate(expression) // prints 29.2 stringify(expression) // prints 4 ^ 2 + 3.3 * 4
  12. 12. There are a lot of mess    case Sum(exp1: Exp, exp2: Exp) =>       evaluate(exp1) + evaluate(exp2) And not only...
  13. 13. Problem of partial interpretation val optimize: Exp => Exp = {    case Multiply(exp1, exp2) if exp1 == exp2 =>      Square(optimize(exp1))    case other => ??? } Lets improve
  14. 14. going to result types02
  15. 15. Generalize it sealed trait Exp[T] case class IntValue[T](value: Int) extends Exp[T] case class DecValue[T](value: Double) extends Exp[T] case class Sum[T](exp1: T, exp2: T) extends Exp[T] case class Multiply[T](exp1: T, exp2: T) extends Exp[T] case class Divide[T](exp1: T, exp2: T) extends Exp[T] case class Square[T](exp: T) extends Exp[T]
  16. 16. val expression: Exp[Exp[Exp[Unit]]] = Sum[Exp[Exp[Unit]]](    Square[Exp[Unit]](      IntValue[Unit](4)    ),    Multiply[Exp[Unit]](      DecValue[Unit](3.3),      IntValue[Unit](4)    )  ) Nesting types issue
  17. 17. its like a hiding of part that doesn't matter fixed point types
  18. 18. F[_] is a generic type with a hole, after wrapping of Exp with that we will have Fix[Exp] type. let's add typehack case class Fix[F[_]](unFix: F[Fix[F]])
  19. 19. val expression: Fix[Exp] = Fix(Sum(    Fix(Square(      Fix(IntValue(4))    )),    Fix(Multiply(      Fix(DecValue(3.3)),      Fix(IntValue(4))    ))  )) Hacked code
  20. 20. case class Square[T](exp: T) extends Exp[T] object Square {   def apply(fixExp: Exp[Fix[Exp]]) = Fix[Exp](fixExp) } val expression: Fix[Exp] = Square(    Square(      Square(        IntValue(4)      ))) Let's do it cleaner
  21. 21. time to traverse our structure 03
  22. 22. def map[F[_], A, B](fa: F[A])(f: A=>B): F[B] Functor 911
  23. 23. Scalaz example case class Container[T](data: T) implicit val functor = new Functor[Container] { override def map[A, B](fa: Container[A]) (f: A => B): Container[B] = Container(f(fa.data)) } functor.map(Container(1))(_.toString) // "1" For cats you will have same code
  24. 24. implicit val functor = new Functor[Exp] { override def map[A, B](fa: Exp[A])(f: A => B): Exp[B] = fa match { case IntValue(v) => IntValue(v) case DecValue(v) => DecValue(v) case Sum(v1, v2) => Sum(f(v1), f(v2)) case Multiply(v1, v2) => Multiply(f(v1), f(v2)) case Divide(v1, v2) => Divide(f(v1), f(v2)) case Square(v) => Square(f(v)) } }
  25. 25. catamorphism anamorphism hylomorphism04
  26. 26. “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”, by Erik Meijer generalized folding operation catamorphism
  27. 27. Lets define Algebra type Algebra[F[_], A] = F[A] => A val evaluate: Algebra[Exp, Double] = {    case IntValue(v) => v.toDouble    case DecValue(v) => v    case Sum(v1, v2) => v1 + v2    case Multiply(v1, v2) => v1 * v2    case Divide(v1, v2) => v1 / v2    case Square(v) => Math.sqrt(v)  }
  28. 28. So as a result val expression: Fix[Exp] = Sum(    Multiply(IntValue(4), IntValue(4)),    Multiply(DecValue(3.3), IntValue(4))  ) import matryoshka.implicits._ expression.cata(evaluate) // 29.2
  29. 29. do you remember about partial interpretation? Extra profit val optimize: Algebra[Exp, Fix[Exp]] = {    case Multiply(Fix(exp), Fix(exp2)) if exp == exp2 =>             Fix(Square(exp))    case other => Fix[Exp](other)  } import matryoshka.implicits._ expression.cata(optimize).cata(stringify) // 4 ^ 2 + 3.3 * 4
  30. 30. val evaluate: Exp => Double = {    case DecValue(value) => value    case IntValue(value) => value.toDouble    case Sum(exp1, exp2) =>       evaluate(exp1) + evaluate(exp2)    case Multiply(exp1, exp2) =>       evaluate(exp1) * evaluate(exp2)    case Divide(exp1, exp2) =>       evaluate(exp1) / evaluate(exp2)    case Square(exp) =>      val v = evaluate(exp)      v * v  } type Algebra[F[_], A] val evaluate: Algebra[Exp, Double] = {    case IntValue(v) => v.toDouble    case DecValue(v) => v    case Sum(v1, v2) => v1 + v2    case Multiply(v1, v2) => v1 * v2    case Divide(v1, v2) => v1 / v2    case Square(v) => Math.sqrt(v)  }
  31. 31. catamorphism: F[_] => A  anamorphism: A => F[_]  hylomorphism: F[_] => A => F[_]  Just good to know
  32. 32. Fixed point types is perfect to create DSLs Recursion schemas is composable All you need to use that stuff, you already know from Scala Summary
  33. 33. thank you. any questions?

×