SlideShare a Scribd company logo
Contravariant Functors in Scala
prepending wagons to the train like a CT pro
Piotr Paradziński
ScalaC03.03.2020
1
● PR’s to Scalaz 7 / Cats
○ Scalaz7 github.com/scalaz/scalaz/pull/2020 Day convolution (0,5 year fight translate from Haskell)
○ Scalaz7 github.com/scalaz/scalaz/pull/2028 add Strong Profunctor laws
○ Scalaz7 github.com/scalaz/scalaz/pull/2029 Density comonad
○ Cats github.com/typelevel/cats/pull/2640 replace Strong Profunctor laws (based on CT)
● type_classopedia - wiki about abstractions from CT github.com/lemastero/scala_typeclassopedia
●
● Small fix in (broken links this is how you start!, docs):
○ Haskell Profunctors github.com/ekmett/profunctors/pull/65 github.com/ekmett/profunctors/pull/66
○ Sclaz ZIO github.com/scalaz/scalaz-zio/pulls?utf8=%E2%9C%93&q=+author%3Alemastero SclaC Hackaton
○ yallop/effects-bibliography github.com/yallop/effects-bibliography/pulls?utf8=✓&q=+author%3Alemastero
○ steshaw.org/plt/ (github.com/steshaw/plt/pulls?utf8=✓&q=+author%3Alemastero)
○ cohomolo-gy/haskell-resources github.com/cohomolo-gy/haskell-resources/pull/3
○ passy/awesome-recurion-schemas github.com/passy/awesome-recursion-schemes/pull/22
○ Agda https://github.com/agda/agda/pull/3751
○ awesome-provable https://github.com/awesomo4000/awesome-provable/pull/1
○ Andrej Baure HoTT lectures: https://github.com/andrejbauer/homotopy-type-theory-course/pull/3
○ Cubical TT course by groupoid https://github.com/groupoid/groupoid.space/pull/20
○ statebox/awesome-applied-CT https://github.com/statebox/awesome-applied-ct/issues?q=author%3Alemastero
INPUT => OUTPUT
3
INPUT => OUTPUT
monix.Task[A], Future[A]
Functor[F], Monad[F],
Comonad[F],
Reader
4
INPUT => OUTPUT
monix.Task[A], Future[A]
Functor[F], Monad[F],
Comonad[F],
Reader
Why we focus only on output?
5
INPUT => OUTPUT
Think
backwards!
6
Contravariant Functors
7
Contravariant Functors
8
Prepend wagos to end Append new Locomotive to begin
(at the end) INPUT (to beginning) OUTPUT
Predicate - checks property of type A
case class Predicate[A](fun: A => Boolean)
9
Predicate - complicated one ;)
case class Predicate[A](fun: A => Boolean)
val hasEnoughLength: Predicate[Int] = Predicate(a => a > 3)
10
Can we use length to create Predicate[String]?
case class Predicate[A](fun: A => Boolean)
val hasEnoughLength: Predicate[Int] = Predicate(a => a > 3)
def len(s: String): Int = s.length
val isValidCode: Predicate[String] = ???
11
Predicate - can we map (define Functor)?
case class Predicate[A](fun: A => Boolean)
import cats.Functor
val predicateFuncor: Functor[Predicate] = new Functor[Predicate] {
def map[A, B](fa: Predicate[A])(f: A => B): Predicate[B] = ???
}
12
Predicate - but we can prepend!
case class Predicate[A](fun: A => Boolean)
val hasEnoughLength: Predicate[Int] = Predicate(a => a > 3)
def len(s: String): Int = s.length
val isValidCode: Predicate[String] =
Predicate[String](len andThen hasEnoughLength.fun)
13
case class Predicate[A](fun: A => Boolean)
def contramap[A, B](pred: Predicate[A])(fba: B => A): Predicate[B] =
Predicate[B](fba andThen pred.fun)
Predicate - generalize prepend
14
Example2 - Show
trait Show[F] {
def show(f: F): String
}
Scalaz github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Show.scala#L51-L53
15
Example2 - Can we reuse existing Show?
trait Show[A] {
def show(a: A): String
}
case class Processor(name: String)
case class Multicore(name: String, coreCount: Int)
val sp: Show[Processor] = new Show[Processor] {
override def show(a: Processor): String = s"Processor ${a.name}"
}
def asProcessor(mc: Multicore): Processor = Processor(s"${mc.coreCount} x ${mc.name}")
16
Example2 - Can we define Functor for Show?
trait Show[A] {
def show(a: A): String
}
val showFunctor: Functor[Show] = new Functor[Show] {
override def map[A, B](fa: Show[A])(f: A => B): Show[B] = ???
}
17
Example2 - no! but we can prepend
trait Show[A] {
def show(a: A): String
}
def contramap[A, B](fa: Show[A])(f: B => A): Show[B] = new Show[B] {
override def show(a: B): String = fa.show(f(a))
}
18
Common pattern - prepend to input 1/3
trait Show[A] {
def show(a: A): String
}
def prepend[A, B](fa: Show[A])(f: B => A): Show[B] = new Show[B] {
override def show(a: B): String = fa.show(f(a))
}
19
Common pattern - prepend to input 2/3
case class Predicate[A](fun: A => Boolean)
def prepend[A, B](pred: Predicate[A])(fba: B => A): Predicate[B] =
Predicate[B](fba andThen pred.fun)
20
Common pattern - prepend to input Contravariant
trait InputPrepender[F[_]] {
def prepend[A, B] (fa: F[A])(f: B => A): F[B]
}
21
Mathematicians and names :)
trait Contravariant[F[_]] {
def contramap[A, B] (fa: F[A])(f: B => A): F[B]
}
22
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]
}
23
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)
24
Contravariant Functor
25
Prepend Append
contramap map
to INPUT to OUTPUT
Exercises - Contravariant for scala.math.Equiv
trait Equiv[T] {
def equiv(x: T, y: T): Boolean
}
val EquivContra: Contravariant[Equiv] = new Contravariant[Equiv] {
override def contramap[A, B](fa: Equiv[A])(f: B => A): Equiv[B] = ???
}
Much more:
https://github.com/lemastero/contravariant_profunctor_exercises/blob/master/src/main/scala/contra_pro/Exercise1_Contravariant.
scala
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
}
27
Contravariant - example Function1
def function1Contravariant[R]: Contravariant[? => R] =
new Contravariant[? => R] {
def contramap[A, B](r: A => R)(f: B => A) = r compose f
}
Glorified compose of Function1 !!!
28
Contravariant - example Reader (1)
case class Reader[C, V](run: C => V)
29
Contravariant - example Reader - Functor
case class Reader[C, V](run: C => V)
def readerFunctor[C] = new Functor[Reader[C,?]] {
def map[A, B](x: Reader[C, A])(f: A => B): Reader[C, B] =
Reader(x.run andThen f)
}
30
Contravariant - example Reader - Monad
case class Reader[C, V](run: C => V)
def readerMonad[C] = new Monad[Reader[C, ?]] {
def map[A, B](x: Reader[C, A])(f: A => B): Reader[C, B] =
Reader(x.run andThen f)
def pure[A](a: A): Reader[C, A] =
new Reader(_ => a)
def flatMap[A, B](ma: Reader[C, A])(f: A => Reader[C, B]) = ???
}
31
Contravariant - example Reader - Contravariant
case class Reader[C, V](run: C => V)
def readerContra[V] = new Contravariant[Reader[?, V]] {
def contramap[A, B](fa: Reader[A, V])(f: B => A):
Reader[B, V] = Reader(f andThen fa.run)
}
32
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
33
Contravariant - laws in Scala
34
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
35
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 :)
36
Contravariant * Contravariant = Covariant
Compose contravariant functors:
https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/Contravariant.scala#L11-L15
Input of your input is not my input
But it’s input is ...
https://github.com/lemastero/scala_typeclassopedia/blob/master/src/main/scala/contravariant/HoFStructure.scala
37
Contravariant Functors everywhere
● Kafka producer
● HTTP endpoints
● DB Repository
● S3 client
● ...
38
Contravariant Functors everywhere but why?
We don’t want to map … and change HttpApi[Json] into HttpApi[Ints]
We might want to:
● provide part of configuration
● change config file path to parsed case class with configuration
● set execution context for all operations
● provide dependency like AvroKafkaDeserializer and schema registry config
(clients don’t have to worry about it)
● add defaults and require only Option[Config]
● ...
39
Contravariant - examples in open source libs
Encoder in Scodec:
github.com/scodec/scodec/blob/series/1.11.x/shared/src/main/scala/scodec/Encoder.scala#L40-L47
Schedule/ZSink/ZQueue in ZIO (contramap, provideSome):
https://github.com/zio/zio/search?q=contramap&unscoped_q=contramap
Logger
https://github.com/zio/zio-logging/issues/7
JSON Encoder in Circe
https://github.com/circe/circe/blob/master/modules/core/shared/src/main/scala/io/circe/Encoder.scala#L53-L55
40
https://gitlab.haskell.org/ghc/ghc/issues/14767
https://github.com/ghc/ghc/blob/master/libraries/base/changelog.md#41200-21-september-2018
Contravariant part of Haskell GHC 8.6.1 in 2018
41
Contravariant - discrimination sort
youtube.com/watch?v=cB8DapKQz-I
Sorting in linear time
Edward Kmett in Haskell
In Scala?
42
Divide
(Contravariant Semigroupal - in Cats)
43
case class Serializer[A](run: A => Array[Byte])
val strSerial = Serializer[String](_.getBytes)
val intSerial = Serializer[Int](_.toString.getBytes)
GOTO Github:
https://github.com/lemastero/contravariant_profunctor_exercises/blob/master/src/test/scala/contra_pro/DivideSpec.scala
Divide (1) - Serialization
44
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?
45
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
46
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)
47
val fragAsTuple: Fragment => (String, Int) =
frag => (frag.name, frag.size)
val fragSerial: Serializer[Fragment] =
Divide[Serializer].divide(strSerial, intSerial)(fragAsTuple)
Divide (5)
48
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
49
https://github.com/lemastero/scala_typeclassopedia/blob/master/Contravariant.MD
#divide-contravariant-apply
Divide - Laws & derived methods
50
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 - Challenge
51
Big Picture
52
Functor - Signature
def map[A,B](fa: F[A])(f: A => B): F[B] Functor
53
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
54
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
55
Contravariant Functors - arrows reversed
//def map (F[A], A => B): F[B] Functor
def contramap (F[A], B => A): 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)
56
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 :)
57
Thank you :)
58

More Related Content

What's hot

The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming Language
John De Goes
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
John De Goes
 
Idiomatic C++
Idiomatic C++Idiomatic C++
Idiomatic C++
Federico Ficarelli
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
Hang Zhao
 
Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence) Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence)
wahab khan
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
John De Goes
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
Hang Zhao
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
Piotr Paradziński
 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2
Philip Schwarz
 
Functors
FunctorsFunctors
Functors
Philip Schwarz
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generators
Philip Schwarz
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
Hang Zhao
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
Introduction To Lisp
Introduction To LispIntroduction To Lisp
Introduction To Lisp
kyleburton
 
Core csharp and net quick reference
Core csharp and net quick referenceCore csharp and net quick reference
Core csharp and net quick reference
ilesh raval
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Philip Schwarz
 
Monad Fact #2
Monad Fact #2Monad Fact #2
Monad Fact #2
Philip Schwarz
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
John De Goes
 
Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'
Philip Schwarz
 

What's hot (19)

The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming Language
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
 
Idiomatic C++
Idiomatic C++Idiomatic C++
Idiomatic C++
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
 
Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence) Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence)
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2
 
Functors
FunctorsFunctors
Functors
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generators
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Introduction To Lisp
Introduction To LispIntroduction To Lisp
Introduction To Lisp
 
Core csharp and net quick reference
Core csharp and net quick referenceCore csharp and net quick reference
Core csharp and net quick reference
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
 
Monad Fact #2
Monad Fact #2Monad Fact #2
Monad Fact #2
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
 
Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'
 

Similar to Contravariant functors in scala

Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
Scalac
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Peng Cheng
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
Oliver Daff
 
Java 8
Java 8Java 8
Java 8
vilniusjug
 
Functional Programming Concepts for Imperative Programmers
Functional Programming Concepts for Imperative ProgrammersFunctional Programming Concepts for Imperative Programmers
Functional Programming Concepts for Imperative Programmers
Chris
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
Lecture 3
Lecture 3Lecture 3
Lecture 3
Muhammad Fayyaz
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
pramode_ce
 
Scala in a nutshell by venkat
Scala in a nutshell by venkatScala in a nutshell by venkat
Scala in a nutshell by venkat
Venkateswaran Kandasamy
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
Martin Odersky
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
Wojciech Pituła
 
Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
daewon jeong
 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantages
Sergei Winitzki
 
Scala @ TomTom
Scala @ TomTomScala @ TomTom
Scala @ TomTom
Eric Bowman
 
Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers
STX Next
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
Bartosz Kosarzycki
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 
Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In Scala
Skills Matter
 
Scala Collections : Java 8 on Steroids
Scala Collections : Java 8 on SteroidsScala Collections : Java 8 on Steroids
Scala Collections : Java 8 on Steroids
François Garillot
 
Programming Android Application in Scala.
Programming Android Application in Scala.Programming Android Application in Scala.
Programming Android Application in Scala.
Brian Hsu
 

Similar to Contravariant functors in scala (20)

Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Java 8
Java 8Java 8
Java 8
 
Functional Programming Concepts for Imperative Programmers
Functional Programming Concepts for Imperative ProgrammersFunctional Programming Concepts for Imperative Programmers
Functional Programming Concepts for Imperative Programmers
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Lecture 3
Lecture 3Lecture 3
Lecture 3
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Scala in a nutshell by venkat
Scala in a nutshell by venkatScala in a nutshell by venkat
Scala in a nutshell by venkat
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
 
Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantages
 
Scala @ TomTom
Scala @ TomTomScala @ TomTom
Scala @ TomTom
 
Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In Scala
 
Scala Collections : Java 8 on Steroids
Scala Collections : Java 8 on SteroidsScala Collections : Java 8 on Steroids
Scala Collections : Java 8 on Steroids
 
Programming Android Application in Scala.
Programming Android Application in Scala.Programming Android Application in Scala.
Programming Android Application in Scala.
 

Recently uploaded

KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
SOCRadar
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
Hironori Washizaki
 
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise EditionWhy Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Envertis Software Solutions
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
lorraineandreiamcidl
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Undress Baby
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
SMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API ServiceSMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API Service
Yara Milbes
 

Recently uploaded (20)

KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
 
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise EditionWhy Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
SMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API ServiceSMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API Service
 

Contravariant functors in scala

  • 1. Contravariant Functors in Scala prepending wagons to the train like a CT pro Piotr Paradziński ScalaC03.03.2020 1
  • 2. ● PR’s to Scalaz 7 / Cats ○ Scalaz7 github.com/scalaz/scalaz/pull/2020 Day convolution (0,5 year fight translate from Haskell) ○ Scalaz7 github.com/scalaz/scalaz/pull/2028 add Strong Profunctor laws ○ Scalaz7 github.com/scalaz/scalaz/pull/2029 Density comonad ○ Cats github.com/typelevel/cats/pull/2640 replace Strong Profunctor laws (based on CT) ● type_classopedia - wiki about abstractions from CT github.com/lemastero/scala_typeclassopedia ● ● Small fix in (broken links this is how you start!, docs): ○ Haskell Profunctors github.com/ekmett/profunctors/pull/65 github.com/ekmett/profunctors/pull/66 ○ Sclaz ZIO github.com/scalaz/scalaz-zio/pulls?utf8=%E2%9C%93&q=+author%3Alemastero SclaC Hackaton ○ yallop/effects-bibliography github.com/yallop/effects-bibliography/pulls?utf8=✓&q=+author%3Alemastero ○ steshaw.org/plt/ (github.com/steshaw/plt/pulls?utf8=✓&q=+author%3Alemastero) ○ cohomolo-gy/haskell-resources github.com/cohomolo-gy/haskell-resources/pull/3 ○ passy/awesome-recurion-schemas github.com/passy/awesome-recursion-schemes/pull/22 ○ Agda https://github.com/agda/agda/pull/3751 ○ awesome-provable https://github.com/awesomo4000/awesome-provable/pull/1 ○ Andrej Baure HoTT lectures: https://github.com/andrejbauer/homotopy-type-theory-course/pull/3 ○ Cubical TT course by groupoid https://github.com/groupoid/groupoid.space/pull/20 ○ statebox/awesome-applied-CT https://github.com/statebox/awesome-applied-ct/issues?q=author%3Alemastero
  • 4. INPUT => OUTPUT monix.Task[A], Future[A] Functor[F], Monad[F], Comonad[F], Reader 4
  • 5. INPUT => OUTPUT monix.Task[A], Future[A] Functor[F], Monad[F], Comonad[F], Reader Why we focus only on output? 5
  • 8. Contravariant Functors 8 Prepend wagos to end Append new Locomotive to begin (at the end) INPUT (to beginning) OUTPUT
  • 9. Predicate - checks property of type A case class Predicate[A](fun: A => Boolean) 9
  • 10. Predicate - complicated one ;) case class Predicate[A](fun: A => Boolean) val hasEnoughLength: Predicate[Int] = Predicate(a => a > 3) 10
  • 11. Can we use length to create Predicate[String]? case class Predicate[A](fun: A => Boolean) val hasEnoughLength: Predicate[Int] = Predicate(a => a > 3) def len(s: String): Int = s.length val isValidCode: Predicate[String] = ??? 11
  • 12. Predicate - can we map (define Functor)? case class Predicate[A](fun: A => Boolean) import cats.Functor val predicateFuncor: Functor[Predicate] = new Functor[Predicate] { def map[A, B](fa: Predicate[A])(f: A => B): Predicate[B] = ??? } 12
  • 13. Predicate - but we can prepend! case class Predicate[A](fun: A => Boolean) val hasEnoughLength: Predicate[Int] = Predicate(a => a > 3) def len(s: String): Int = s.length val isValidCode: Predicate[String] = Predicate[String](len andThen hasEnoughLength.fun) 13
  • 14. case class Predicate[A](fun: A => Boolean) def contramap[A, B](pred: Predicate[A])(fba: B => A): Predicate[B] = Predicate[B](fba andThen pred.fun) Predicate - generalize prepend 14
  • 15. Example2 - Show trait Show[F] { def show(f: F): String } Scalaz github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Show.scala#L51-L53 15
  • 16. Example2 - Can we reuse existing Show? trait Show[A] { def show(a: A): String } case class Processor(name: String) case class Multicore(name: String, coreCount: Int) val sp: Show[Processor] = new Show[Processor] { override def show(a: Processor): String = s"Processor ${a.name}" } def asProcessor(mc: Multicore): Processor = Processor(s"${mc.coreCount} x ${mc.name}") 16
  • 17. Example2 - Can we define Functor for Show? trait Show[A] { def show(a: A): String } val showFunctor: Functor[Show] = new Functor[Show] { override def map[A, B](fa: Show[A])(f: A => B): Show[B] = ??? } 17
  • 18. Example2 - no! but we can prepend trait Show[A] { def show(a: A): String } def contramap[A, B](fa: Show[A])(f: B => A): Show[B] = new Show[B] { override def show(a: B): String = fa.show(f(a)) } 18
  • 19. Common pattern - prepend to input 1/3 trait Show[A] { def show(a: A): String } def prepend[A, B](fa: Show[A])(f: B => A): Show[B] = new Show[B] { override def show(a: B): String = fa.show(f(a)) } 19
  • 20. Common pattern - prepend to input 2/3 case class Predicate[A](fun: A => Boolean) def prepend[A, B](pred: Predicate[A])(fba: B => A): Predicate[B] = Predicate[B](fba andThen pred.fun) 20
  • 21. Common pattern - prepend to input Contravariant trait InputPrepender[F[_]] { def prepend[A, B] (fa: F[A])(f: B => A): F[B] } 21
  • 22. Mathematicians and names :) trait Contravariant[F[_]] { def contramap[A, B] (fa: F[A])(f: B => A): F[B] } 22
  • 23. 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] } 23
  • 24. 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) 24
  • 26. Exercises - Contravariant for scala.math.Equiv trait Equiv[T] { def equiv(x: T, y: T): Boolean } val EquivContra: Contravariant[Equiv] = new Contravariant[Equiv] { override def contramap[A, B](fa: Equiv[A])(f: B => A): Equiv[B] = ??? } Much more: https://github.com/lemastero/contravariant_profunctor_exercises/blob/master/src/main/scala/contra_pro/Exercise1_Contravariant. scala 26
  • 27. Contravariant - example Function1 def function1Contravariant[R]: Contravariant[? => R] = new Contravariant[? => R] { def contramap[A, B](r: A => R)(f: B => A) = r compose f } 27
  • 28. Contravariant - example Function1 def function1Contravariant[R]: Contravariant[? => R] = new Contravariant[? => R] { def contramap[A, B](r: A => R)(f: B => A) = r compose f } Glorified compose of Function1 !!! 28
  • 29. Contravariant - example Reader (1) case class Reader[C, V](run: C => V) 29
  • 30. Contravariant - example Reader - Functor case class Reader[C, V](run: C => V) def readerFunctor[C] = new Functor[Reader[C,?]] { def map[A, B](x: Reader[C, A])(f: A => B): Reader[C, B] = Reader(x.run andThen f) } 30
  • 31. Contravariant - example Reader - Monad case class Reader[C, V](run: C => V) def readerMonad[C] = new Monad[Reader[C, ?]] { def map[A, B](x: Reader[C, A])(f: A => B): Reader[C, B] = Reader(x.run andThen f) def pure[A](a: A): Reader[C, A] = new Reader(_ => a) def flatMap[A, B](ma: Reader[C, A])(f: A => Reader[C, B]) = ??? } 31
  • 32. Contravariant - example Reader - Contravariant case class Reader[C, V](run: C => V) def readerContra[V] = new Contravariant[Reader[?, V]] { def contramap[A, B](fa: Reader[A, V])(f: B => A): Reader[B, V] = Reader(f andThen fa.run) } 32
  • 33. 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 33
  • 34. Contravariant - laws in Scala 34
  • 36. 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 :) 36
  • 37. Contravariant * Contravariant = Covariant Compose contravariant functors: https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/Contravariant.scala#L11-L15 Input of your input is not my input But it’s input is ... https://github.com/lemastero/scala_typeclassopedia/blob/master/src/main/scala/contravariant/HoFStructure.scala 37
  • 38. Contravariant Functors everywhere ● Kafka producer ● HTTP endpoints ● DB Repository ● S3 client ● ... 38
  • 39. Contravariant Functors everywhere but why? We don’t want to map … and change HttpApi[Json] into HttpApi[Ints] We might want to: ● provide part of configuration ● change config file path to parsed case class with configuration ● set execution context for all operations ● provide dependency like AvroKafkaDeserializer and schema registry config (clients don’t have to worry about it) ● add defaults and require only Option[Config] ● ... 39
  • 40. Contravariant - examples in open source libs Encoder in Scodec: github.com/scodec/scodec/blob/series/1.11.x/shared/src/main/scala/scodec/Encoder.scala#L40-L47 Schedule/ZSink/ZQueue in ZIO (contramap, provideSome): https://github.com/zio/zio/search?q=contramap&unscoped_q=contramap Logger https://github.com/zio/zio-logging/issues/7 JSON Encoder in Circe https://github.com/circe/circe/blob/master/modules/core/shared/src/main/scala/io/circe/Encoder.scala#L53-L55 40
  • 42. Contravariant - discrimination sort youtube.com/watch?v=cB8DapKQz-I Sorting in linear time Edward Kmett in Haskell In Scala? 42
  • 44. case class Serializer[A](run: A => Array[Byte]) val strSerial = Serializer[String](_.getBytes) val intSerial = Serializer[Int](_.toString.getBytes) GOTO Github: https://github.com/lemastero/contravariant_profunctor_exercises/blob/master/src/test/scala/contra_pro/DivideSpec.scala Divide (1) - Serialization 44
  • 45. 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? 45
  • 46. 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 46
  • 47. 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) 47
  • 48. val fragAsTuple: Fragment => (String, Int) = frag => (frag.name, frag.size) val fragSerial: Serializer[Fragment] = Divide[Serializer].divide(strSerial, intSerial)(fragAsTuple) Divide (5) 48
  • 49. 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 49
  • 51. 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 - Challenge 51
  • 53. Functor - Signature def map[A,B](fa: F[A])(f: A => B): F[B] Functor 53
  • 54. 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 54
  • 55. 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 55
  • 56. Contravariant Functors - arrows reversed //def map (F[A], A => B): F[B] Functor def contramap (F[A], B => A): 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) 56
  • 57. 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 :) 57