Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Simplicity in composition

Simplicity in composition

Avatar for Adelbert Chang

Adelbert Chang

September 18, 2017
Tweet

More Decks by Adelbert Chang

Other Decks in Programming

Transcript

  1. Simplicity in composition Adelbert Chang @adelbertchang Scala World 2017 Adelbert

    Chang (@adelbertchang) Simplicity in composition Scala World 2017 1 / 67
  2. Composition A: type (set) of values ⊕: A × A

    → A Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
  3. Composition A: type (set) of values ⊕: A × A

    → A 1A : identity for ⊕ Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
  4. Composition A: type (set) of values ⊕: A × A

    → A 1A : identity for ⊕ (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
  5. Composition A: type (set) of values ⊕: A × A

    → A 1A : identity for ⊕ (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z) x = x ⊕ 1A = 1A ⊕ x Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
  6. (A → A, ◦, a → a) Adelbert Chang (@adelbertchang)

    Simplicity in composition Scala World 2017 5 / 67
  7. trait Monoid[A] { def combine(x: A, y: A): A def

    empty: A } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 6 / 67
  8. 1 2 3 4 5 6 7 8 Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 7 / 67
  9. 3 3 4 5 6 7 8 Adelbert Chang (@adelbertchang)

    Simplicity in composition Scala World 2017 8 / 67
  10. 6 4 5 6 7 8 Adelbert Chang (@adelbertchang) Simplicity

    in composition Scala World 2017 9 / 67
  11. 1 2 3 4 5 6 7 8 Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 12 / 67
  12. 1 2 3 4 5 6 7 8 3 7

    11 15 10 26 36 Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 16 / 67
  13. Associative composition allows for modular decomposition and reasoning. Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 17 / 67
  14. Composing programs (F[A], F[B]) => F[(A, B)] Adelbert Chang (@adelbertchang)

    Simplicity in composition Scala World 2017 22 / 67
  15. Composing programs F( ): type of program Adelbert Chang (@adelbertchang)

    Simplicity in composition Scala World 2017 23 / 67
  16. Composing programs F( ): type of program ⊗ : F(A)

    × F(B) → F((A, B)) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
  17. Composing programs F( ): type of program ⊗ : F(A)

    × F(B) → F((A, B)) η : A → F(A) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
  18. Composing programs F( ): type of program ⊗ : F(A)

    × F(B) → F((A, B)) η : A → F(A) (fa ⊗ fb) ⊗ fc ∼ = fa ⊗ (fb ⊗ fc) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
  19. Composing programs F( ): type of program ⊗ : F(A)

    × F(B) → F((A, B)) η : A → F(A) (fa ⊗ fb) ⊗ fc ∼ = fa ⊗ (fb ⊗ fc) fa ∼ = fa ⊗ ηUnit ∼ = ηUnit ⊗ fa Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
  20. Composing programs def zipOption[A, B] (oa: Option[A], ob: Option[B]): Option[(A,

    B)] = (oa, ob) match { case (Some(a), Some(b)) => Some((a, b)) case _ => None } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 24 / 67
  21. Composing programs def zipOption[A, B] (oa: Option[A], ob: Option[B]): Option[(A,

    B)] = (oa, ob) match { case (Some(a), Some(b)) => Some((a, b)) case _ => None } def pureOption[A](a: A): Option[A] = Some(a) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 24 / 67
  22. Composing programs def zipList[A, B] (la: List[A], lb: List[B]): List[(A,

    B)] = la match { case Nil => Nil case h :: t => lb.map((h, _)) ++ zipList(t, lb) } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 25 / 67
  23. Composing programs def zipList[A, B] (la: List[A], lb: List[B]): List[(A,

    B)] = la match { case Nil => Nil case h :: t => lb.map((h, _)) ++ zipList(t, lb) } def pureList[A](a: A): List[A] = List(a) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 25 / 67
  24. Composing programs def zipFunction[A, B, X] (f: X => A,

    g: X => B): X => (A, B) = (x: X) => (f(x), g(x)) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 26 / 67
  25. Composing programs def zipFunction[A, B, X] (f: X => A,

    g: X => B): X => (A, B) = (x: X) => (f(x), g(x)) def pureFunction[A, X](a: A): X => A = (_: X) => a Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 26 / 67
  26. /** Same as Applicative */ trait Monoidal[F[_]] { def zip[A,

    B](fa: F[A], fb: F[B]): F[(A, B)] def pure[A](a: A): F[A] /* def map[A, B](fa: F[A])(f: A => B): F[B] */ } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 27 / 67
  27. User input Password reqs Features Latest posts Sign-up form Featured

    Welcome page Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 28 / 67
  28. Composing programs (F[A], F[B]) => F[(A, B)] Adelbert Chang (@adelbertchang)

    Simplicity in composition Scala World 2017 29 / 67
  29. Composing independent programs (F[A], F[B]) => F[(A, B)] Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 30 / 67
  30. Composing dependent programs (F[A], A => F[B]) => F[B] Adelbert

    Chang (@adelbertchang) Simplicity in composition Scala World 2017 32 / 67
  31. Composing dependent programs F( ): type of program 1> =

    >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
  32. Composing dependent programs F( ): type of program > >=:

    (F(A) × A → F(B)) → F(B) 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
  33. Composing dependent programs F( ): type of program > >=:

    (F(A) × A → F(B)) → F(B) η : A → F(A) 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
  34. Composing dependent programs F( ): type of program > >=:

    (F(A) × A → F(B)) → F(B) η : A → F(A) (fa > >= f ) > >= g = fa > >= (f >=> g)1 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
  35. Composing dependent programs F( ): type of program > >=:

    (F(A) × A → F(B)) → F(B) η : A → F(A) (fa > >= f ) > >= g = fa > >= (f >=> g)1 f (x) = η(x) > >= f 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
  36. Composing dependent programs F( ): type of program > >=:

    (F(A) × A → F(B)) → F(B) η : A → F(A) (fa > >= f ) > >= g = fa > >= (f >=> g)1 f (x) = η(x) > >= f fa = fa > >= η 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
  37. Composing dependent programs def flatMapOption[A, B] (oa: Option[A], f: A

    => Option[B]): Option[B] = oa match { case Some(a) => f(a) case None => None } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 34 / 67
  38. Composing dependent programs def flatMapList[A, B] (la: List[A], f: A

    => List[B]): List[B] = la match { case Nil => Nil case h :: t => f(h) ++ flatMapList(t, f) } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 35 / 67
  39. Composing dependent programs def flatMapFunction[A, B, X] (fa: X =>

    A, f: A => (X => B)): X => B = (x: X) => f(fa(x))(x) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 36 / 67
  40. trait Monad[F[_]] { def flatMap[A, B](fa: F[A])(f: A => F[B]):

    F[B] def pure[A](a: A): F[A] } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 37 / 67
  41. trait Monad[F[_]] extends Monoidal[F] { def flatMap[A, B](fa: F[A])(f: A

    => F[B]): F[B] def pure[A](a: A): F[A] } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 38 / 67
  42. A nicer monad (fa > >= f ) > >=

    g = fa > >= (f >=> g) f (x) = η(x) > >= f fa = fa > >= η Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 39 / 67
  43. A nicer monad f : A → F(B) g :

    B → F(C) h : C → F(D) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 40 / 67
  44. A nicer monad f : A → F(B) g :

    B → F(C) h : C → F(D) (f >=> g) >=> h = f >=> (g >=> h) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 40 / 67
  45. A nicer monad f : A → F(B) g :

    B → F(C) h : C → F(D) (f >=> g) >=> h = f >=> (g >=> h) f = f >=> η = η >=> f Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 40 / 67
  46. User info Friends Cookies Logs Profile Recommendations News feed Adelbert

    Chang (@adelbertchang) Simplicity in composition Scala World 2017 41 / 67
  47. Category theory objects: A, B, C ... Adelbert Chang (@adelbertchang)

    Simplicity in composition Scala World 2017 43 / 67
  48. Category theory objects: A, B, C ... arrows: f :

    A → B, g : B → C ... Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
  49. Category theory objects: A, B, C ... arrows: f :

    A → B, g : B → C ... 1A : A → A Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
  50. Category theory objects: A, B, C ... arrows: f :

    A → B, g : B → C ... 1A : A → A (f ◦ g) ◦ h = f ◦ (g ◦ h) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
  51. Category theory objects: A, B, C ... arrows: f :

    A → B, g : B → C ... 1A : A → A (f ◦ g) ◦ h = f ◦ (g ◦ h) f = f ◦ 1A = 1A ◦ f Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
  52. Category theory B A C g 1B f g◦f 1A

    1C Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 44 / 67
  53. Category theory B A C g 1B f g◦f 1A

    1C Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 44 / 67
  54. Category theory B A C g 1B f g◦f 1A

    1C Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 44 / 67
  55. Category theory: monoids • x y x⊕y 1A Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
  56. Category theory: monoids • x y x⊕y 1A Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
  57. Category theory: monoids • x y x⊕y 1A Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
  58. Category theory: monoids • x y x⊕y 1A Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
  59. Category theory: monads F(B) A F(C) f ?◦f Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 46 / 67
  60. Category theory: monads F(B) A F(C) f ?◦f > >=:

    (F(B) × B → F(C)) → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 46 / 67
  61. Category theory: monads F(B) A F(C) f ?◦f > >=:

    (B → F(C)) → F(B) → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 47 / 67
  62. Category theory: monads F(B) A F(C) g∗ f g∗◦f >

    >=: (B → F(C)) → F(B) → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 48 / 67
  63. Category theory: monads B A C g 1B B→F(B) f

    g ◦f 1A A→F(A) 1C C→F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
  64. Category theory: monads B A C g 1B B→F(B) f

    g ◦f 1A A→F(A) 1C C→F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
  65. Category theory: monads B A C g 1B B→F(B) f

    g ◦f 1A A→F(A) 1C C→F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
  66. Category theory: monads B A C g 1B B→F(B) f

    g ◦f 1A A→F(A) 1C C→F(C) η : X → F(X) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
  67. User info Friends Cookies Logs Profile Recommendations News feed Adelbert

    Chang (@adelbertchang) Simplicity in composition Scala World 2017 50 / 67
  68. What if we have different monoids, monads, etc? Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 51 / 67
  69. Product composition: monoids (Monoid[A], Monoid[B]) => Monoid[(A, B)] Adelbert Chang

    (@adelbertchang) Simplicity in composition Scala World 2017 53 / 67
  70. Product composition: monoids def combine(x: (A, B), y: (A, B)):

    (A, B) = { val a = x._1 combine y._1 val b = x._2 combine y._2 (a, b) } 0Assuming Monoid[A] and Monoid[B] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 54 / 67
  71. Product composition: monoids def combine(x: (A, B), y: (A, B)):

    (A, B) = { val a = x._1 combine y._1 val b = x._2 combine y._2 (a, b) } def empty: (A, B) = (empty[A], empty[B]) 0Assuming Monoid[A] and Monoid[B] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 54 / 67
  72. Product composition: lax monoidal functors type L[X] = (F[X], G[X])

    (Monoidal[F], Monoidal[G]) => Monoidal[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 56 / 67
  73. Product composition: lax monoidal functors def zip[A, B](x: (F[A], G[A]),

    y: (F[B], G[B])): (F[(A, B)], G[(A, B)]) = { val f = x._1 zip y._1 val g = x._2 zip y._2 (f, g) } 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 57 / 67
  74. Product composition: lax monoidal functors def zip[A, B](x: (F[A], G[A]),

    y: (F[B], G[B])): (F[(A, B)], G[(A, B)]) = { val f = x._1 zip y._1 val g = x._2 zip y._2 (f, g) } def pure[A](a: A): (F[A], G[A]) = (a.pure[F], a.pure[G]) 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 57 / 67
  75. Product composition: monads type L[X] = (F[X], G[X]) (Monad[F], Monad[G])

    => Monad[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 58 / 67
  76. Product composition: monads def flatMap[A, B] (xa: (F[A], G[A]))(ff: A

    => (F[B], G[B])): (F[(A, B)], G[(A, B)]) = { val f = xa._1.flatMap(a => ff(a)._1) val g = xa._2.flatMap(a => ff(a)._2) (f, g) } 0Assuming Monad[F] and Monad[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 59 / 67
  77. Nested composition: lax monoidal functors type L[X] = F[G[X]] (Monoidal[F],

    Monoidal[G]) => Monoidal[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 60 / 67
  78. User input Password reqs Features Latest posts Sign-up form Featured

    Welcome page Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 61 / 67
  79. Nested composition: lax monoidal functors def zip[A, B](fga: F[G[A]], fgb:

    F[G[B]]): F[G[(A, B)]] = { val fp: F[(G[A], G[B])] = fga zip fgb fp.map { case (ga, gb) => ga zip gb } } 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 62 / 67
  80. Nested composition: lax monoidal functors def zip[A, B](fga: F[G[A]], fgb:

    F[G[B]]): F[G[(A, B)]] = { val fp: F[(G[A], G[B])] = fga zip fgb fp.map { case (ga, gb) => ga zip gb } } def pure[A](a: A): F[G[A]] = a.pure[G].pure[F] 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 62 / 67
  81. Nested composition: monads type L[X] = F[G[X]] (Monad[F], Monad[G]) =>

    Monad[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 63 / 67
  82. Nested composition: monads type L[X] = F[G[X]] (Monad[F], Monad[G]) =>

    Monad[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 64 / 67
  83. Nested composition: monads def flatMap[A, B](fga: F[G[A]](f: A => F[G[B]]):

    F[G[B]] = 0Assuming Monad[F] and Monad[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 65 / 67
  84. Nested composition: monads def flatMap[A, B](fga: F[G[A]](f: A => F[G[B]]):

    F[G[B]] = fga.flatMap { (ga: G[A]) => ??? } 0Assuming Monad[F] and Monad[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 65 / 67
  85. Review Associative composition allows for modular decomposition and reasoning Adelbert

    Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
  86. Review Associative composition allows for modular decomposition and reasoning Monoids

    compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
  87. Review Associative composition allows for modular decomposition and reasoning Monoids

    compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
  88. Review Associative composition allows for modular decomposition and reasoning Monoids

    compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Monoids compose Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
  89. Review Associative composition allows for modular decomposition and reasoning Monoids

    compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Monoids compose Lax monoidal/applicative functors compose Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
  90. Review Associative composition allows for modular decomposition and reasoning Monoids

    compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Monoids compose Lax monoidal/applicative functors compose Monads in general do not compose See: monad transformers, extensible (algebraic) effects Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
  91. References Equational reasoning at scale - Gabriel Gonzalez http://www.haskellforall.com/2014/07/ equational-reasoning-at-scale.html

    Invariant Shadows - Michael Pilquist http://mpilquist.github.io/blog/2015/06/22/ invariant-shadows-part-2/ All About Applicative - Me! https://www.youtube.com/watch?v=Mn7BtPALFys A categorial view of computational effects - Emily Riehl https://www.youtube.com/watch?v=6t6bsWVOIzs Conceptual Mathematics - F. William Lawvere and Stephen H. Schanuel Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 67 / 67