# Kleisli category
## for Bartosz M. fans
---
## What is a category (recap)
----
**Category** is a collection of "objects" that are linked by "arrows".
A category has two basic properties:
* the ability to compose the arrows **associatively**;
* the existence of an **identity arrow** for each object.
```graphviz
digraph g{
compound=true
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
a->a[label=id]
b->b[label=id]
c->c[label=id]
d->d[label=id]
a->b[label=f,fontsize=30]
b->c[label=g,fontsize=30]
c->d[label=h,fontsize=30]
a->c[label="g.f",fontsize=30,color=green]
}
```
----
### Example: financial processing
* `get_account_state: A -> B`
* `apply_tax_reductions: B -> C`
* `apply_taxes: C -> D`
* `process: A -> D`
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
A->B[label=get_account_state]
B->C[label=apply_tax_reductions]
C->D[label=apply_taxes]
A->D[label="process",color=green]
}
```
Note:
Ok, what if we want to get a bit more information about process?
How are things going?
---
## Embelishment
`f: A -> B`
`f*: A -> (B, log) = B*`
Note:
Lets add a bit more information to our functions. Let them return some textual log.
----
### Embelished finanical system
* `get_account_state*: A -> B*`
* `apply_tax_reductions*: B -> C*`
* `apply_taxes*: C -> D*`
* `process*: ???`
----
### Embelished finanical system
* `get_account_state*: A -> B*`
* `apply_tax_reductions*: B -> C*`
* `apply_taxes*: C -> D*`
* `process*: ???`
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
A, B, C
mb[label="B*",shape=doublecircle]
mc[label="C*",shape=doublecircle]
md[label="D*",shape=doublecircle]
A->mb[label="get_account_state*"]
B->mc[label="apply_tax_reductions*"]
C->md[label="apply_taxes*"]
mb->B[style=dotted]
mc->C[style=dotted]
md->D[style=dotted]
A->D[style=dashed,color=green,label="process*?"]
}
```
Note:
How to compose these functions?
---
## How do we compose embelished functons?
----
```
f*: A -> B* = A -> (B, log)
g*: B -> C* = B -> (C, log)
compose: (A -> B*) -> (B -> C*) -> (A -> C*)
```
----
```
f*: A -> B* = A -> (B, log)
g*: B -> C* = B -> (C, log)
compose: (A -> B*) -> (B -> C*) -> (A -> C*)
```
```
compose(f, g)(a) {
(b, b_log) = f(a)
(c, c_log) = g(b)
return (c, b_log ++ c_log)
}
```
----
### Embelished finanical system
* `get_account_state*: A -> B*`
* `apply_tax_reductions*: B -> C*`
* `apply_taxes*: C -> D*`
* `process*: A -> D*`
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
node [shape=circle] A
node [shape=doublecircle] B, C, D
A->B[style=circle,label="get_account_state*"]
B->C[label="apply_tax_reductions*"]
C->D[label="apply_taxes*"]
A->D[color=green,label="process*"]
}
```
---
## Embelished category
Can we make a category?
We need **identity arrows**
We need **assossiatively composobale** arrows.
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
node [shape=circle] A
node [shape=doublecircle] B, C, D
A->B[style=circle,label="f*"]
B->C[label="g*"]
C->D[label="h*"]
}
```
----
`id . f = f . id`
----
`id . f = f . id`
```
compose: (A -> B*) -> (B -> C*) -> (A -> C*)
```
----
`id . f = f . id`
```
compose: (A -> B*) -> (B -> C*) -> (A -> C*)
```
`id: A -> A*`
---
### Embellished identity
`id . f = f . id`
```
compose: (A -> B*) -> (B -> C*) -> (A -> C*)
```
`id: A -> A*`
`id* (a) = (a, "")`
---
### Assossiative composability
Easy to prove that new arrows are still assossiatively composable
```
compose(f*, compose(g*, h*)) == compose(compose(f*, g*), h*)
```
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
A->B[label="f*"]
B->C[label="g*"]
C->D[label="h*"]
B->D[label="hg*", color=red, style=dashed]
A->C[label="gf*", color=blue, style=dashed]
A->D[label="hgf*", color=green, style=dashed]
}
```
---
## Kleisli category
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
A->B[label="f*"]
B->C[label="g*"]
C->D[label="h*"]
B->D[label="hg*", color=red, style=dashed]
A->C[label="gf*", color=blue, style=dashed]
A->D[label="hgf*", color=green, style=dashed]
A->A[label="id*"]
B->B[label="id*"]
C->C[label="id*"]
D->D[label="id*"]
}
```
----
How do we create Kleisli category:
* Use the same objects
* Morphisms are **Kleisli arrows**:
`f: A -> B*`,
where `B*` is *embelished* `B`
* Identity is `id*`
* Composition of morphisms are defined by *embelishment*.
---
### What is embelishment?
----
*Embelishment* defines the derived type with *additional* information.
----
Additional information can be evaluated later.
For example, *side-effects*.
----
Different emeblishment defines different Kleisli category.
---
### M-word
*Embelishment* is a **Monad**.
----
Our example uses `Writer` monad but there are many others:
`Option/Maybe`, `Future`, `Try`, `List`, etc.
----
Kleisli category is defined by a monad that defines *identity* and *composition*.
----
#### Bonus
We can define a monad that does **nothing**
```
f*: A -> B
f == f*
```
It defines Kleisli category for our first example:
```graphviz
digraph g{
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
A->B[label=get_account_state]
B->C[label=apply_tax_reductions]
C->D[label=apply_taxes]
A->D[label="process",color=green]
}
```
---
## Show me the code!
----
### Writer monad
----
What interface do monad have?
----
Monad should be able to take an embelished function
and apply on inner value.
----
```scala
final case class Writer[A](value: A, s: String) {
def flatMap[B](f: A => Writer[B]): Writer[B] = {
val b = f(value)
Writer(b.value, s ++ b.s)
}
}
```
---
### Composition
```scala
def compose[A, B, C](f: A ⇒ Writer[B],
g: B ⇒ Writer[C]): A ⇒ Writer[C] =
a ⇒ f(a).flatMap(g)
```
---
## Thank you!
Interesting reading:
* [From design patterns to category theory](https://blog.ploeh.dk/2017/10/04/from-design-patterns-to-category-theory/)
* [Monads Made Hard](http://www.stephendiehl.com/posts/monads.html)
{"metaMigratedAt":"2023-06-14T22:32:31.642Z","metaMigratedFrom":"YAML","title":"Kleisli category","breaks":true,"description":"Short introduction into Kleisli category","contributors":"[{\"id\":\"2850e30a-d2ab-4db7-afe4-c8862c04c364\",\"add\":11020,\"del\":4566}]"}