Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
Próximos SlideShares
Carregando em…5
×

# Big picture of category theory in scala with deep dive into contravariant and profunctors

A big picture of category theory in Scala - starting from regular functors with additional structure (Apply, Applicative, Monad) to Comonads. Usually, we think about structures like Monoids in a monoidal category with particular tensor. In here I analyze just signatures of different abstractions.

Exploration of Contravariant functors as a way to model computation "backward" or abstract over input with the ability to prepend operation. Examples for predicates, sorting, show and function input (or any other function parameter except the last one).

Profunctors as abstraction unifying Functors and Contravariant functors to model both input and output. Example for Profunctor - function with one argument.

Relation to Bifunctors, Kan extensions, Adjunctions, and Free constructions.

• Full Name
Comment goes here.

Are you sure you want to Yes No
• Entre para ver os comentários

### Big picture of category theory in scala with deep dive into contravariant and profunctors

1. 1. Big picture of Category Theory in Scala with deep dive into: - Contravariant - Profunctors Piotr Paradziński ScalaC27.03.2019 1
3. 3. Big Picture 3
4. 4. Category Theory abstractions in Scala - Functor, Apply, Applicative 4
5. 5. Category Theory abstractions there is more - Functor, Apply, Applicative - Monads: State, Writer, Reader, IO, Option, Eiter, Validated, List/Vector 5
6. 6. Functor - Signature def map[A,B](fa: F[A])(f: A => B): F[B] Functor 6
7. 7. Apply - Signature def map[A,B](fa: F[A])(f: A => B): F[B] Functor def ap[A,B](ff: F[A => B])(fa: F[A]): F[B] Apply 7
8. 8. Applicative - Signature def map[A,B](fa: F[A])(f: A => B): F[B] Functor def ap[A,B](ff: F[A => B])(fa: F[A]): F[B] Apply def pure[A](value: A): F[A] Applicative 8
9. 9. Monad - Signature def map[A,B](fa: F[A])(f: A => B): F[B] Functor def ap[A,B](ff: F[A => B])(fa: F[A]): F[B] Apply def pure[A](value: A): F[A] Applicative def flatMap[A,B](fa: F[A])(f: A => F[B]): F[B] Monad 9
10. 10. Signatures - similar? def map[A,B](fa: F[A])(f: A => B): F[B] Functor def ap[A,B](ff: F[A => B])(fa: F[A]): F[B] Apply def pure[A](value: A): F[A] Applicative def flatMap[A,B](fa: F[A])(f: A => F[B]): F[B] Monad 10
11. 11. Covariant Functors Signatures - Pattern def map A => B => F[B] Functor def ap F[A => B] => F[B] Apply def pure () => B => F[B] Applicative* def flatMap A => F[B] => F[B] Monad http://blog.tmorris.net/posts/scala-type-class-hierarchy/index.html 11
12. 12. Category Theory abstractions in Scala - Functor, Apply, Applicative - Monads: State, Writer, Reader, IO, Option, Eiter, Validated, List/Vector, Free - Comonads: NonEmptyList, Stream, Store, Context, Cofree 12
13. 13. Comonads - signatures def map[A,B](fa: F[A])(f: A => B): F[B] Functor def coflatMap[A, B](fa: F[A])(f: F[A] => B): F[B] CoflatMap def coflatten[A](fa: F[A]): F[F[A]] CoflatMap def extract[A](x: F[A]): A Comonad 13
14. 14. Comonads - Signatures - Pattern //def flatMap (F[A], A => F[B]): F[B] FlatMap def coflatMap (F[A], F[A] => B): F[B] CoflatMap //def flatten F[F[A]]: F[A] Monad def coflatten F[A]: F[F[A]] CoflatMap //def pure A : F[A] Applicative def extract F[A]: A Comonad 14
15. 15. Category Theory abstractions in Scala - Functor, Apply, Applicative - Monads: State, Writer, Reader, IO, Option, Eiter, Validated, List/Vector - Comonads: NonEmptyList, Stream, Store, Context - Contravariant, Divide, Divisible 15
16. 16. Big Picture Contravariant Functors 16
17. 17. Contravariant - signature trait Contravariant[F[_]] { def contramap[A, B] (fa: F[A])(f: B => A): F[B] } 17
18. 18. Contravariant - like a Functor but flip! trait Functor[F[_]] { def map[A, B] (fa: F[A]) (f: A => B): F[B] } trait Contravariant[F[_]] { def contramap[A, B] (fa: F[A]) (f: B => A): F[B] } 18
19. 19. Contravariant Functor - input + ability to prepend Functor is “full of” A’s (container A, function producing A) F[A] we can map A => B and we get F[B] F[A] we can contramap B => A and we get F[B] Contravariant “needs” A (index of container, function consuming A) 19
20. 20. case class Predicate[A](fun: A => Boolean) Example in GIthub: https://github.com/lemastero/scala_typeclassopedia/blob/master/src/test/scala/contravariant/Contravaria ntSpec.scala Contravariant - example Predicate (1) 20
21. 21. case class Predicate[A](fun: A => Boolean) val predicateContravariantFunctor = new Contravariant[Predicate] { def contramap[A, B](pred: Predicate[A])(fba: B => A): Predicate[B] = Predicate[B](fba andThen pred.fun) } Contravariant - example Predicate (2) 21
22. 22. val pl = Predicate[String](_.length > 5) pl.fun("Contravariant") // true val pr1 = Predicate[Int](_ > 5) pr1.fun(42) // true Contravariant - example Predicate (3) 22
23. 23. val pl = Predicate[String](_.length > 5) pl.fun("Contravariant") // true val pr1 = Predicate[Int](_ > 5) pr1.fun(42) // true val len: String => Int = _.length val pr = Contravariant[Predicate].contramap(pr1)(len) pr.fun("Contravariant") // true Contravariant - example Predicate (4) 23
24. 24. Contravariant - example Show trait Show[F] { def show(f: F): String } implicit val showContravariant = new Contravariant[Show] { def contramap[A, B](r: Show[A])(f: B => A): Show[B] = new Show[B] { def show(b: B): String = r.show(f(b)) } } Scalaz github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Show.scala#L51-L53 24
25. 25. Contravariant - example Op (Haskell like) case class Op[R,A](getOp: A => R) def opContravariant [R] = new Contravariant[Op[ R, ?]] { def contramap[A, B](fa: Op[R, A])(f: B => A): Op[R, B] = Op(f andThen fa.getOp) } 25
26. 26. Contravariant - example Function1 def function1Contravariant[R]: Contravariant[? => R] = new Contravariant[? => R] { def contramap[A, B](r: A => R)(f: B => A) = r compose f } 26
27. 27. Contravariant - FunctionN parameters all but last trait Function2[-T1, -T2, +R]{ def apply(v1: T1, v2: T2): R } trait Function3[-T1, -T2, -T3, +R]{ def apply(v1: T1, v2: T2, v3: T3): R } //... All parameters are in negative position, co we could define Contravariant instance for it. (Or even BiContravariant, TriContravariant, ... if they existed :) 27
28. 28. Contravariant - example Reader (1) case class Reader[C, V](run: C => V) 28
32. 32. Contravariant - example Encoder Encoder in scodec: github.com/scodec/scodec/blob/series/1.11.x/shared/src/main/scala/scodec/Encoder.scala#L4 0-L47 has Contravariant instance github.com/scodec/scodec-cats/blob/master/shared/src/main/scala/scodec/interop/cats/CatsI nstances.scala#L121-L123 32
33. 33. Contravariant - Resources Haskell George Wilson: Contravariant Functors: The Other Side of the Coin : https://www.youtube.com/watch?v=IJ_bVVsQhvc Michael noyman - Covariance and Contravariance fpcomplete.com/blog/2016/11/covariance-contravariance Tom Ellis - 24 Days of Hackage: contravariant https://ocharles.org.uk/blog/guest-posts/2013-12-21-24-days-of-hackage-contravariant.html (nice example with actors producing Behaviour a) https://packdeps.haskellers.com/reverse/contravariant (100+ Haskell libs using Contravariant package) 33
34. 34. Contravariant - discrimination sort youtube.com/watch?v=cB8DapKQz-I Sorting in linear time Edward Kmett in Haskell In Scala? 34
35. 35. Functor laws fmap id = id fmap f . fmap g = fmap (f . g) Contravariant laws contramap id = id contramap f . contramap g = contramap (g . f) Contravariant - laws in Haskell 35
36. 36. Cats: github.com/typelevel/cats/blob/master/laws/src/main/scala/cats/laws/ContravariantLaws.scala Scalaz 7: github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Contravariant.scala#L59-L68 scala_typeclassopedia: github.com/lemastero/scala_typeclassopedia#contravariant-contravariant-functor Contravariant - laws in Scala 36
37. 37. Contravariant - laws in Scala 37
38. 38. Divide (Contravariant Semigroupal - in Cats) 38
39. 39. case class Serializer[A](run: A => Array[Byte]) val strSerial = Serializer[String](_.getBytes) val intSerial = Serializer[Int](_.toString.getBytes) Github: https://github.com/lemastero/scala_typeclassopedia/blob/master/src/test/scala/contravaria nt/DivideSpec.scala Divide (1) - Serialization 39
40. 40. val fragmentSerial = Serializer[Fragment] { frag => val a1 = strSerial.run(frag.name) val a2 = intSerial.run(frag.size) a1 ++ a2 } val serialized = fragmentSerial.run(Fragment("Area", 52)) new String(serialized ) mustBe "Area52" Divide (2) - How to combine serializers? 40
41. 41. trait Divide[F[_]] extends Contravariant[F] { def divide[A,B,C](f: A => (B,C), fb: F[B], fc: F[C]): F[A] } Divide (3) - abstraction 41
42. 42. val fragmentDivide: Divide[Serializer] = new Divide[Serializer] { def divide2[A1, A2, Z](s1: => Serializer[ A1], s2: => Serializer[ A2])(f: Z => (A1, A2)): Serializer[ Z] = Serializer{ frag => val (a1,a2) = f(frag) s1.run(a1) ++ s2.run(a2) } } Divide (4) 42
43. 43. val fragAsTuple: Fragment => (String, Int) = frag => (frag.name, frag.size) val fragSerial: Serializer[Fragment] = Divide[Serializer].divide(strSerial, intSerial)(fragAsTuple) Divide (5) 43
44. 44. val fragAsTuple: Fragment => (String, Int) = frag => (frag.name, frag.size) val fragSerial: Serializer[Fragment] = Divide[Serializer].divide(strSerial, intSerial)(fragAsTuple) val serialized = fragSerial.run(Fragment("Area", 52)) new String(serialized ) mustBe "Area52" Divide - Run 44
45. 45. https://github.com/lemastero/scala_typeclassopedia#divide-co ntravariant-apply Divide - Laws & derived methods 45
46. 46. Define full laws for Divide as in Haskell hackage.haskell.org/package/contravariant/docs/Data-Functor-Contravariant-Divisible.html#g:4 Not simplified as in Scalaz and Cats! Contravariant - Divide - Exercise 46
47. 47. Contravariant Functors (1) def contramap(fa: F[A],f: B => A): F[B] Contravariant def divide(f: A => (B,C), fb: F[B],fc: F[C]): F[A] Divide def conquer: F[A] Divisible There is no Contravariant Monad There is Contravariant Traversable, Alternative: https://www.youtube.com/watch?v=cB8DapKQz-I Edward Kmett, Discrimination is Wrong, 2015 47
48. 48. Contravariant Functors (2) - arrows reversed //def map (F[A], A => B): F[B] Functor def contramap (F[A], A <= B): F[B] Contravariant (Contravariant Functor) //def map2 ((A,B) => Z, F[A], F[B]): F[Z] Apply (not ap!) def divide (Z => (A,B), F[A], F[B]): F[Z] Divide (Contravariant Apply) //def pure: ( () => A ) => F[A] Applicative def conquer: ( A <= () ) => F[A] Divisible (Contravariant Applicative) 48
49. 49. Bigger Picture Profunctors 49
50. 50. Category Theory abstractions in Scala - Functor, Apply, Applicative - Monads: State, Writer, Reader, IO, Option, Eiter, Validated, List/Vector - Comonads: NonEmptyList, Stream, Store, Context - Contravariant, Divide, Divisible - Profunctor, Profunctor Strong, Profunctor Choice, Arrows, Kleisli 50
51. 51. trait Profunctor[P[_, _]] { def dimap[X,Y,Z,W](ab: X => Y, cd: Z => W): P[Y, Z] => P[X, W] } Profunctor 51
52. 52. trait Profunctor[P[_, _]] { def dimap[X,Y,Z,W](ab: X => Y, cd: Z => W): P[Y, Z] => P[X, W] } ● contramap on first type ( P[Y, _] is Contravariant ) ● map on second type ( P[_, Z] is Functor ) Profunctor = Contravariant + Functor 52
53. 53. trait Profunctor[P[_, _]] { def dimap[X,Y,Z,W](ab: X => Y, cd: Z => W): P[Y, Z] => P[X, W] // derived methods def lmap[A,B,C](f: A => B): P[B,C] => P[A,C] = dimap[A,B,C,C](f,identity[C]) def rmap[A,B,C](f: B => C): P[A,B] => P[A,C] = dimap[A,A,B,C](identity[A], f) } Profunctor - derived methods 53
54. 54. Haskell ● dimap id id == id ● dimap (f . g) (h . i) == dimap g h . dimap f i Scala a bit more verbose Profunctor - Laws 54
55. 55. val function1: Profunctor[Function1] = new Profunctor[Function1] { def dimap[X, Y, Z, W](f: X => Y, g: Z => W): (Y => Z) => (X => W) = h => f andThen (g compose h) def lmap[A,B,C](f: A => B): (B => C) => (A => C) = f andThen def rmap[A,B,C](f: B => C): (A => B) => (A => C) = f compose } Profunctor - Example Function1 55
56. 56. val f: String => Int = _.length case class Person(name: String, age: Int) val preF: Person => String = _.name val postF: Int => Boolean = _ > 5 Profunctor - Example Function1 - setup 56
57. 57. val f: String => Int = _.length case class Person(name: String, age: Int) val preF: Person => String = _.name val postF: Int => Boolean = _ > 5 Profunctor[Function1].dimap(f)(preF)(postF)( Person("Foo", 100) ) Profunctor - Example Function1 - true ? 57
58. 58. val f: String => Int = _.length case class Person(name: String, age: Int) val preF: Person => String = _.name val postF: Int => Boolean = _ > 5 Profunctor[Function1].dimap(f)(preF)(postF)( Person("Foo", 100) ) // false Profunctor - Example Function1 58
59. 59. ● Haskell opaleye: https://github.com/tomjaguarpaw/haskell-opaleye/search?q=dimap&unscoped_q=dimap ● Monadic profunctors for bidirectional programming - blog post https://blog.poisson.chat/posts/2017-01-01-monadic-profunctors.html ● Kleisli Arrow Profunctor - Usage 59
60. 60. Strong Profunctor 60
61. 61. trait Strong[P[_, _]] extends Profunctor[P] { def first[X,Y,Z](pab: P[X, Y]): P[(X, Z), (Y, Z)] } Profunctor - Strong 61
62. 62. trait Strong[P[_, _]] extends Profunctor[P] { def first[X,Y,Z](pab: P[X, Y]): P[(X, Z), (Y, Z)] // derived methods def second[X,Y,Z](pab: P[X, Y]): P[(Z, X), (Z, Y)] } Profunctor - Strong - Derived methods 62
63. 63. val functionStrong: Strong[Function1] = new Strong[Function1] with Function1Profunctor { def first[X, Y, Z](pab: X => Y): Function1[( X, Z), (Y, Z)] = (xz: (X, Z)) => (pab(xz._1) , xz._2) } Profunctor - Strong - Function1 63
64. 64. val functionStrong: Strong[Function1] = new Strong[Function1] with Function1Profunctor { def first[X, Y, Z](pab: X => Y): Function1[( X, Z), (Y, Z)] = (xz: (X, Z)) => (pab(xz._1) , xz._2) } Profunctor[Function1].first(len)(( "foo", 42)) == (3,42) Profunctor - Strong - Function1 64
65. 65. PR #2640 Strong Profunctor Laws: https://github.com/typelevel/cats/pull/2640 Profunctor - Strong Laws 65
66. 66. Description: https://github.com/lemastero/scala_typeclassopedia#profunctor Translation to Scala early (very early pre-alpha): https://github.com/lemastero/scala_typeclassopedia/tree/master/src/main/scala/profunctor Profunctor hierarchy - big, not in Scala yet 66
67. 67. Strong Profunctor == Arrow Model IO using Profunctors/Arrows? 67
68. 68. Bigger Picture Everything else 68
69. 69. Category Theory abstractions in Scala - Functor, Apply, Applicative - Monads: State, Writer, Reader, IO, Option, Eiter, Validated, List/Vector - Comonads: NonEmptyList, Stream, Store, Context - Contravariant, Divide, Divisible - Profunctor, Profunctor Strong, Profunctor Choice, Arrows, Kleisli - Traversable, Foldable (+ Monoid, Semigroup) - Kan extensions, Yoneda, Coyoneda, Density, Codensity - Free Monads, Free Applicative, Cofree, Free Alternative, Free Arrows - ... Profunctor optics, Cartesian Closed Categories, Day Convolution 69
70. 70. Big Picture of Category Theory in Scala 70
71. 71. Nice papers - Different encodings of CT like Sjoerd Visscher data-category: hackage.haskell.org/package/data-category-0.7/docs/Data-Category.html - Bifunctors: Joker, Clown, Biff, … - nice papers - Arrows … - nice papers - Distributive (Comonad Applicative) - nice papers - Adjunctions between Monads, Applicative, Arrows - nice papers - Monad, Applicative, Arrow as Monoid in Monoidal Category with given tensor (Functor Composition, Sum, Product, Day convolution) - nice papers - Recursion schemas (Fold, Unfolds, Fix point) - people talk about 3, exists 20+ 71
72. 72. Alternative encoding - Different encodings of CT like Sjoerd Visscher data-category: hackage.haskell.org/package/data-category-0.7/docs/Data-Category.html - Proofs of Category Theory in Coq - Proofs of Category Theory using Univalent Foundations (related to HoTT) in Coq (UniMath/UniMath) https://github.com/UniMath/UniMath/tree/master/UniMath/CategoryTheory 72
73. 73. How to learn Category Theory 1) Translate to Scala, Kata? wiki.haskell.org/Typeclassopedia, Edward Kmett libs 2) Describe github.com/lemastero/scala_typeclassopedia 3) In Scala 3 4) Talk using new vocabulary! 73
74. 74. Good general theory does not search for the maximum generality, but for the right generality. Saunders Mac Lane Choose the right level of abstraction, to see the problem more clearly Eugenia Cheng, Category in Life https://www.youtube.com/watch?v=ho7oagHeqNc Thank you :) 74
75. 75. Thank you :) 75