<<

It’s All About

Uberto Barbini @ramtop https://medium.com/@ramtop About me

OOP programmer Agile

TDD Finance Kotlin Industry Blog: https://medium.com/@ ramtop Twitter: @ ramtop

#morphisms#VoxxedVienna @ramtop Map of this presentation

Monoid

Functor Natural Transformation Yoneda Applicative Morphisms all the way down...

#morphisms#VoxxedVienna @ramtop I don’t care about Monads, why should I? Neither do I what I care about is y el is to define system behaviour ec Pr

#morphisms#VoxxedVienna @ramtop This presentation will be a success if most of you will not fall asleep

#morphisms#VoxxedVienna @ramtop This presentation will be a success if You will consider that Functional Programming is about transformations and preserving properties. Not (only) lambdas and flatmap

#morphisms#VoxxedVienna @ramtop What is this Category thingy?

Invented in 1940s “with the goal of understanding the processes that preserve mathematical structure.” “ is about relation between things” “General abstract nonsense”

#morphisms#VoxxedVienna @ramtop Once upon a time there was a Category of Stuffed Toys and a Category of Tigers...

#morphisms#VoxxedVienna @ramtop A Category is defined in 5 steps: 1) A collection of Objects

#morphisms#VoxxedVienna @ramtop A Category is defined in 5 steps: 2) A collection of Arrows

#morphisms#VoxxedVienna @ramtop A Category is defined in 5 steps: 3) Each Arrow works on 2 Objects

#morphisms#VoxxedVienna @ramtop A Category is defined in 5 steps: 4) Arrows can be combined

#morphisms#VoxxedVienna @ramtop A Category is defined in 5 steps: 5) Each Object has an Identity (an arrow pointing to itself)

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop A Category Example Tube Map: Objects → stations stations Arrows → stations travel routes Each Arrows connect 2 stations Arrow composition is travelling along the line Identity Arrow is staying in the same station

#morphisms#VoxxedVienna @ramtop London Tube Category

#morphisms#VoxxedVienna @ramtop Monoid Category Monad

Functor Natural Transformation Yoneda Applicative This presentation is a Category as well!

#morphisms#VoxxedVienna @ramtop AddItem Ready NewOrder Dispatch Dispatched Cancel Close Return Cancelled Closed Returned Event Source Category https://skillsmatter.com/skillscasts/11486-functional-cqrs

#morphisms#VoxxedVienna @ramtop Functional Programming is also a Category

Each has a Category: Types are the objects and Functions are the morphisms. Partial functions don’t have a defined return for all inputs. In reality all programming functions are partial: they can raise Exceptions or never end. They always have an hidden return of Bottom Type (⊥))

#morphisms#VoxxedVienna @ramtop Change of mindset!

Object Oriented Functional Living Bacteria Gears and Pipes Opaque Transparent Hidden State Immutable State Interfaces Type Classes

#morphisms#VoxxedVienna @ramtop Kotlin for functional programming

● Nullable and not-nullable types ● Type Aliases ● Class extensions ● Tail recursion ● Pattern matching (when) ● Arrow-kt bindinds with ● Arrow-kt Typeclasses (?)

#morphisms#VoxxedVienna @ramtop arrow-kt.io

#morphisms#VoxxedVienna @ramtop KEEP-87 TypeClasses

#morphisms#VoxxedVienna @ramtop Purity and Immutability For the Category morphisms to work in programming we need Purity and Immutability. But they are not a goal per se, only a necessity for the main goal: composition and transformation. Ultimately everything is converted in assembly which is neither pure nor immutable. We need those quality only for exposed code

#morphisms#VoxxedVienna @ramtop Monoid

What about the category of morphisms of a category? Are they composable? It’s a Category with a single Object and lots of Morphisms

A Category with only one Object is a Monoid

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop Programming with Monoids A with two methods combine → stations monoid append empty → stations neutral element

(x <> y) <> z = x <> (y <> z) -- associativity empty <> x = x -- left identity x <> empty = x -- right identity

#morphisms#VoxxedVienna @ramtop Generics Type Contructors

List is just an abstract type to build List List List etc.

#morphisms#VoxxedVienna @ramtop Type Class vs Interface

● Interfaces “unify” different types: Cat and Dogs can be treated as Animals ● Type Classes “group” types with similar behaviour, without hiding their types: Cats and Dogs can both form couples but cats can mate only with cats and dogs with dogs. You cannot represent that with interfaces.

#morphisms#VoxxedVienna @ramtop Typeclass Instances ● Typeclasses work with instances (like a singleton) ● List is not a Monoid nor a Functor nor a Monad but it has an (or more) instance of Monoid one of Functor and one of Monad ● Technically we implement instances as an interface with a singletons specific implementation. ● We can have different implementation for difference in evaluation, for example because of concurrency

#morphisms#VoxxedVienna @ramtop Enough talk, let’s see the code!

Monoid TypeClass Instances...

...Give us the combine extension

#morphisms#VoxxedVienna @ramtop The future (?) extension interface Monoid { infix fun T.add(t: T): T } extension object IntMonoid: Monoid { inline fun Int.add(t: Int) = this + t } inline fun sum(t1: T, t2: T, t3: T, with Monoid) = t1 add t2 add t3 fun main() { sum(1, 2, 3) //no boxing because of inlining }

#morphisms#VoxxedVienna @ramtop Transformers a.k.a. Functors

!! nt ta or mp I ry Ve

#morphisms#VoxxedVienna @ramtop Functors

Functors can map both objects (types) and (functions) between two categories Functors map must preserve the structure and some properties But can also work inside the same category (Endofunctors)

#morphisms#VoxxedVienna @ramtop Functor Laws Functor is a TypeClass with a Map function that works like this. Id is the identity function. map id x = x map (g <> f) = map g <> map f)

Passing the ID function must return the original value Map must honour associativity of two functions

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop Try Functor

Keep a context and Map operation on `it

Failure without Exception #morphisms#VoxxedVienna @ramtop Functors are also Forklifts Lift a function from A --> B to F --> F

val lifted = Try.functor().lift {x:String -> x.toInt()}

lifted(Try.Success("42")) //Try.Success(42)

#morphisms#VoxxedVienna @ramtop Yoneda Lemma Yoneda's lemma concerns functors from a fixed category C to the category of sets, Set. If C is a locally small category (i.e. the hom- sets are actual sets and not proper classes), then each object A of C gives rise to a natural functor to Set called a hom-functor.

#morphisms#VoxxedVienna @ramtop Yoneda Lemma F.map(A→B): F (? must be A) The actual implementation is useful to compose of mappings without executing until we decide

combine all the maps in one and then apply it. No copies of List

#morphisms#VoxxedVienna @ramtop Natural Transformations A natural transformation provides a way of transforming one functor into another while respecting the internal structure of the categories involved.

Transforming Data → Functions Transforming Functions → Functors Transforming Functors → Natural Transformations

#morphisms#VoxxedVienna @ramtop Natural Transformations

#morphisms#VoxxedVienna @ramtop Natural Transformations

val list = Try {"3".toInt()}.toOption().toList() //[3]

val fail = Try {"xyz".toInt()}.toOption().toList() //[]

#morphisms#VoxxedVienna @ramtop Combining Functors We can imagine 2 ways to combine 2 functors

F + F = F F map F = F or F * F = F flatmap (a → F>) = F a

#morphisms#VoxxedVienna @ramtop Applicative Functors ● We can combine a value inside a Functor with a function inside another Functor ● If the function want more than 1 param, it will return a function with x-1 params. ● Applicative can apply: ● F applied to FB> to create F

#morphisms#VoxxedVienna @ramtop Try Applicative Functor

Silly example of function that can raise an Exception

Exception raised!

#morphisms#VoxxedVienna @ramtop The M word... ● What about a category of (endo)functors? ● Some functors have a monoid instance, others not. ● How can we call the Category of Endofunctors with a Monoid instance? A Monad is just a Monoid in the category of Endofunctors, what's the problem?

#morphisms#VoxxedVienna @ramtop Monad Recipe

#morphisms#VoxxedVienna @ramtop Monads Allow Sequences of Instructions

#morphisms#VoxxedVienna @ramtop Monads Binding From here: val university: IO = getStudent("John Smith").flatMap { student -> getUniversity(student.universityId).flatMap { university -> getDean(university.deanId) } }

To here: val university: IO = IO.monad().binding { val student = getStudent("John Smith").bind() val university = getUniversity(student.universityId).bind() val dean = getDean(university.deanId).bind() dean } #morphisms#VoxxedVienna @ramtop Functional Programming Dilemma: Perfectly Pure Programs are Perfectly Useless s Effect Enter

#morphisms#VoxxedVienna @ramtop courtesy of Reader Monad fun getUser(userId:String):Reader { fun getCommonFriends(u1: User, u2: User): Reader>

What’s happen if user cannot be fetched?

Runs here

#morphisms#VoxxedVienna @ramtop Monads Zoo ● Option All Monads are also Functors and ● Try Applicative, but the opposite is not true. ● List Each Monad as it’s specific logic on top ● Either of the Monads Laws ● Reader These are already available in many ● Writer libraries but you can extend and create ● State your own. ● IO ● Free

#morphisms#VoxxedVienna @ramtop Why studying Categories?

Morphisms allows you to work at compile time with your Domain Knowledge Learn how to compose functions and preserve properties Monads and other typeclasses should emerge from your code, not the other way round Learn a common terminology and the reasons behind that

#morphisms#VoxxedVienna @ramtop How to use morphisms in real world programs?

#morphisms#VoxxedVienna @ramtop Real World Examples

Web Server as a function github.com/http4k/http4k

Functional Domain Design github.com/uberto/anticapizzeria

#morphisms#VoxxedVienna @ramtop To learn more: Category Theory for Programmers bartoszmilewski.com Cats in scala typelevel.org/cats Arrow in Kotlin arrow-kt.io

If you enjoyed please follow me on twitter and medium @ramtopramtop

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop

#morphisms#VoxxedVienna @ramtop Endofunctors ● In programming we only work with Endofunctors in the Category of our types ● Endofunctor map a => F a where F a is a type constructor in the same category of a (the type system category) ● Endofunctors are very important because we can compose them!

#morphisms#VoxxedVienna @ramtop Higher Kinded Types

In Java we cannot abstract at more than one level like List> or ignoring the second level List> But in Functional programming makes sense generalise over the container or context like: X + f(A)->B = X

#morphisms#VoxxedVienna @ramtop Monads Laws

"The diagram commutes" means that the map produced by following any path through the diagram is the same.

#morphisms#VoxxedVienna @ramtop List Applicative Transform a standard List in a Arrow List (ListK)

Can you guess how it work?

#morphisms#VoxxedVienna @ramtop List Map2

Exactly same result

#morphisms#VoxxedVienna @ramtop Reader: A Functor on functions

Val userId = 123 val reader = Reader{dbUrl:String -> DbConn(dbUrl)} val name = reader.run("myDbConn") .map{it.getUser(userId) } .map{it.name} .value() //"Joe"

#morphisms#VoxxedVienna @ramtop Purity Bubbles + Events = Actors

#morphisms#VoxxedVienna @ramtop "Rather than thinking about function purity as a goal, you have to think about which properties you want your program to preserve." @raulraja

Perfectly Pure Programs are Perfectly Useless

#morphisms#VoxxedVienna @ramtop London Tube Map is a Monoid! (if you squint hard enough)

#morphisms#VoxxedVienna @ramtop Ok… but why using a Object Oriented Language for Functional Programming at all?

#morphisms#VoxxedVienna @ramtop Conclusions: why functional programming? More composition Less sugar Less boilerplate Different thinking Less repetitions VS Performance issues Less bugs Complex state Less need for tests More precision Easier concurrency Different testing style

#morphisms#VoxxedVienna @ramtop Monads Transformers

● Monads don’t compose

#morphisms#VoxxedVienna @ramtop Validated example

● Better than Try

#morphisms#VoxxedVienna @ramtop Kleisli Arrows Original problem: Monads don’t allow for concurrency Arrows can be useful in Reactive Functional Programming Kleisli is a type of Arrow for a Monadic context It’s old ReaderT actually

#morphisms#VoxxedVienna @ramtop Arrows

#morphisms#VoxxedVienna @ramtop CandyDispenser

● Code example ● Let’s bring all together ● We have a function Seed → stations (Seed, Candy) ● Another one (State, Input) → stations State ● How can we combine them? ● We want (Dispenser, [Input]) → stations (Dispenser, [Candy])

#morphisms#VoxxedVienna @ramtop Adjoint Functors Functor F from category D to C Functor G from C to D Every adjunction F, G, ε, , η gives rise to an associated 〈 〉 monad T, η , μ in the category D. 〈 〉

#morphisms#VoxxedVienna @ramtop