<style>
.reveal .code-wrapper {width: fit-content; max-width: 200%; font-size: xxx-large;}
.reveal img {max-width: 200%;}
.reveal pre {max-height: 600px;}
.reveal pre code {max-height: 600px; padding: 10px !important;}
.reveal .hljs-ln-numbers {display: none;}
code {color: #c7254e;}
.fold {position: relative; left: -130px;}
.tweaglogo {height: 60px; margin: 0 !important;}
.haskellatwork {position: relative; left: -450px;}
.list {position: relative; left: -90px; top: -70px;}
.traverse {position: relative; left: -90px;}
.traversePetFor {position: realtive; left: -40px;}
.traverseParseEmail {position: relative; left: -60px;}
.parseEmail {position: relative; left: -35px;}
.foldlM {position: relative; left: -90px;}
.httpCountDogs {position: relative; left: -115px;}
.reveal table th, .reveal table td {border-right: 1px solid; border-color: white;}
.reveal table thead tr th:last-child, .reveal table tbody tr td:last-child {border-right: none;}
.reveal table tr td:first-child {font-weight: bold;}
.highlight {color: #d9480f}
.backgrounds {background-image: url(https://github.com/marcosh/functional-loops/blob/main/images/Tweag_Preso_BGND.svg?raw=true);}
.reveal .slide-background {
background-image: url(https://github.com/marcosh/functional-loops/blob/main/images/T_Mark_Orange.svg?raw=true);
height: 50px;
width: 50px;
position: absolute;
top: 20px;
right: 35px;
}
.mermaid {text-align: center !important; background-color:#2d2d2d !important;}
</style>
# State machines with [`crem`](https://github.com/tweag/crem)
<img src="https://raw.githubusercontent.com/tweag/crem/main/logo/crem-transparent.png" width="200">
---
![the picture that explains everything](http://marcosh.github.io/img/the-picture-that-explains-everything.png)
---
### <span style="color: orange">Domain events</span>
![event](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-event.png)
Events relevant for domain experts
---
### <span style="color: dodgerblue">Commands</span>
![command](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-command.png)
User intentions/actions/decisions
---
### <span style="color: lightyellow">Read models</span>
![read model](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-read-model.png)
Data needed in order to make decisions
---
### <span style="color: yellow">Aggregates</span>
![aggregate](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-aggregate.png)
Decide what happens on commands
---
### <span style="color: orchid">Policies</span>
![policy](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-policy.png)
Reactive logic that takes place after an event
---
### <span style="color: lightgreen">Projections</span>
![projection](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-projection.png)
Aggregate data from events
---
## <span style="color: yellow">Aggregates</span>, <span style="color: lightgreen">projections</span> and <span style="color: orchid">policies</span> could be implemented as state machines
---
### <span style="color: yellow">Aggregates</span>
![aggregate-command-event](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-aggregate-command-event.png)
From <span style="color: dodgerblue">commands</span> to <span style="color: orange">events</span>
---
### <span style="color: lightgreen">Projections</span>
![projection-event-read-model](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-projection-event-read-model.png)
From <span style="color: orange">events</span> to <span style="color: lightyellow">read models</span>
---
### <span style="color: orchid">Policies</span>
![policy-event-command](https://github.com/marcosh/ddd-machines-dddeurope/raw/main/images/the-picture-that-explains-everything-policy-event-command.png)
From <span style="color: orange">events</span> to <span style="color: dodgerblue">commands</span>
---
## How should we encode a state machine?
---
### Mealy machines
```haskell
data Mealy state input output = Mealy
{ initialState :: state
, action :: state -> input -> (state, output)
}
```
---
### [Mealy machines](https://hackage.haskell.org/package/machines-0.7.3/docs/Data-Machine-Mealy.html#t:Mealy)
```haskell
newtype Mealy input output = Mealy
{ runMealy
:: input
-> (output, Mealy input output)
}
```
---
## Machines are composable
---
### Sequential
```haskell
Sequential
:: Mealy a b
-> Mealy b c
-> Mealy a c
```
```mermaid
%%{init: {'theme':'dark'}}%%
stateDiagram-v2
direction LR
a --> b
b --> c
```
---
### Parallel
```haskell
Parallel
:: Mealy a b
-> Mealy c d
-> Mealy (a, c) (b, d)
```
```mermaid
%%{init: {'theme':'dark'}}%%
stateDiagram-v2
direction LR
state fork <<fork>>
(a,c) --> fork
fork --> a
fork --> c
a --> b
c --> d
state join <<join>>
b --> join
d --> join
join --> (b,d)
```
---
### Alternative
```haskell
Alternative
:: Mealy a b
-> Mealy c d
-> Mealy (Either a c) (Either c d)
```
```mermaid
%%{init: {'theme':'dark'}}%%
stateDiagram-v2
direction LR
eitherac: Either a c
state fork <<choice>>
eitherac --> fork
fork --> a
fork --> c
a --> b
c --> d
state join <<choice>>
b --> join
d --> join
join --> eitherbd
eitherbd: Either b d
```
---
### Feedback
```haskell
Feedback
:: Mealy a [b]
-> Mealy b [a]
-> Mealy a [b]
```
```mermaid
%%{init: {'theme':'dark'}}%%
stateDiagram-v2
direction LR
a --> b: []
b --> a: []
```
---
## This encoding can only be run
note: Once we defined a machine, the only way to extract information about it, is to run it, giving it inputs and observing its outputs
---
### What about documentation?
---
### What about invariant enforcement?
---
## Strengthening the type
```haskell
data Machine
(topology :: Topology vertex)
input
output
```
---
### Topology
```mermaid
%%{init: {'theme':'dark'}}%%
stateDiagram-v2
NoData --> CollectedUserData
CollectedUserData --> CollectedLoanDetailsFirst
CollectedUserData --> ReceivedCreditBureauDataFirst
CollectedLoanDetailsFirst --> CollectedAllData
ReceivedCreditBureauDataFirst --> CollectedAllData
```
---
### Adding the `Topology` in the type
---
Allows us to enforce execution of allowed transitions
---
Allows us to retrieve information about our state machine without running it
---
### But...
---
### Composition becomes harder
```haskell
Sequential
:: Machine t1 a b
-> Machine t2 b c
-> Machine ??? a c
```
---
Requires computation at the type level
---
Breaks usage of standard typeclasses like `Arrow` or `Category`
---
## Can we get the best of both worlds?
---
```haskell
data StateMachine input output where
```
---
```haskell
data StateMachine input output where
Basic
:: Machine topology input output
-> StateMachine input output
```
---
```haskell
data StateMachine input output where
...
Sequential
:: StateMachine a b
-> StateMachine b c
-> StateMachine a c
```
---
```haskell
data StateMachine input output where
...
Parallel
:: StateMachine a b
-> StateMachine c d
-> StateMachine (a, c) (b, d)
```
---
```haskell
data StateMachine input output where
...
Alternative
:: StateMachine a b
-> StateMachine c d
-> StateMachine (Either a c) (Either b d)
```
---
```haskell
data StateMachine input output where
...
Feedback
:: StateMachine a [b]
-> StateMachine b [a]
-> StateMachine a [b]
```
---
```mermaid
%%{init: {'theme':'dark'}}%%
graph TD
A[Sequential] --> B[Parallel]
A --> C[Alternative]
B --> D[Machine 1]
B --> E[Machine 2]
C --> F[Machine 3]
C --> G[Machine 4]
```
---
## Composable
---
## Executable
---
## Representable
---
For the `Basic` constructor, we demote information from the type level to the value level
---
For the other contructor, we compose the information according to the constructor semantic
---
### We can draw our machines
---
<img alt="risk manager" src="https://mermaid.ink/svg/pako:eNqlVF1PwjAU_SvkPmkyCGCBbQ8mCvqkxkj0wSwhzXad1a4lXUdAsv9u9-HcCMgMfepOz73n3PbubsGXAYILsaYaZ4yGikbd1dATHbNysEPDUGGY7bYFnK0KXDzIGdX0BZXG9b7zqeQcfY3Bc4yqJfVOUjFDTRmPb5mK9eGQJ_SRrTCYKgyYvk4U0iQTORJWKV1x_renenmdbvfyxMqa1EMJ29ffLvGpt7TfzyH3R--0hZ1_5E7rzbqUnPmbeqcWyOLsvMH-bepMqOAUJ2WGhn5DQckPY4VJ0VCp0MWciZDjYwXs8bqjXlHrOpEvhU91XaSEdmupOcrSlSywIEIVURaY3ztP4oF-xwg9cM02oOrTA0-khpcsA6N4Y95CKnDfKI_RAppoOd8IH1ytEvwhlSOiYi2peJWy8Q3uFtbgkv6oN7ZtZ0xscjEZWbABdziY9IjjODaZkMFw0HdIasFXHt_vGQrmFu6LkZRPpvQbS36R_g" height="600">
---
## Demo time
![the hobbit](https://ready64.org/giochi/full/h/hobbit_01.png)
[The Hobbit code](https://github.com/tweag/crem/blob/main/examples/Crem/Example/TheHobbit.hs)
[The Hobbit map](https://mermaid.live/edit#pako:eNp9ksFuwjAMhl-l8rlFUNrS5rDLNmkHkKZtpykXi3gQkTqoTdEY4t0Xyqhox3aKrf-L_Sf2AZZWEQioHTp60LiqsIx2sWTJbw0zmbne0BMaI3lufYqsai9V1pj63hBWmleSX_SOWNGJWuja7Re2YYeaL-QzunV3C3c0LB5E0V1wVb8LW-FPI2d14KWft8iVvRvqtcWOvFm6rw5e2ktvtz31-MfzUD5_VBf_MgshlFSVqJUf4EFyEEhwaypJgvChwmojQfLRc81W-fk-Ku1sBeIDTU0hYOPs656XIFzV0AX6WYKO2iK_W9vLQRzgE0RUTIpsNB4XsyzN4jSEPYikiEdpPomLPI_9kR5D-GpvF6NZkuTTdDpJsmk-G3ucWjuL8wK2e3j8Bgbo5M8)
note:
`cabal run hobbit-game`
`cabal run hobbit-map`
---
## That's all!
{"metaMigratedAt":"2023-06-17T22:13:16.174Z","metaMigratedFrom":"YAML","title":"State machines with [`crem`](https://github.com/tweag/crem)","breaks":true,"slideOptions":"{\"progress\":true,\"controls\":false,\"slideNumber\":false}","contributors":"[{\"id\":\"0893b955-bc9c-4ecc-b38c-6072b5bc1ecd\",\"add\":10403,\"del\":711}]"}