What happens when the request is invalid?
public class TransactionRequest {
public static String transact(Request request) {
Transaction transaction = coerce(request);
transaction = persist(transaction);
notify(transaction);
}
}
Slide 33
Slide 33 text
What happens when the request is invalid?
public class TransactionRequest {
public static String transact(Request request) {
Transaction transaction = coerce(request);
transaction = persist(transaction);
notify(transaction);
}
}
Or the transaction is not persisted?
Slide 34
Slide 34 text
What happens when the request is invalid?
Or the transaction is not persisted?
Or the notification is not sent?
public class TransactionRequest {
public static String transact(Request request) {
Transaction transaction = coerce(request);
transaction = persist(transaction);
notify(transaction);
}
}
We need to handle errors
Exceptions = GOTO
When dealing with flow control
Slide 41
Slide 41 text
Before
(defn transact! [transaction]
(-> transaction
coerce
persist!
notify!))
We need to handle errors
Slide 42
Slide 42 text
Before
(defn transact! [transaction]
(-> transaction
coerce
persist!
notify!))
After
(defn transact! [transaction]
(->= transaction
coerce
persist!
notify!))
We need to handle errors
Slide 43
Slide 43 text
Before
Functional
(defn transact! [transaction]
(-> transaction
coerce
persist!
notify!))
After
(defn transact! [transaction]
(->= transaction
coerce
persist!
notify!))
We need to handle errors
Slide 44
Slide 44 text
Monads
Slide 45
Slide 45 text
coerce persist! notify!
Composing functions
Slide 46
Slide 46 text
Composing functions
coerce persist! notify!
Slide 47
Slide 47 text
Return the context with the result
type Return = {:ok value} | {:error error}
Slide 48
Slide 48 text
coerce persist!
How do we compose functions?
Slide 49
Slide 49 text
Enters the bind function
coerce persist!
bind
:ok
:error
Slide 50
Slide 50 text
coerce persist! notify!
Composing with bind
Slide 51
Slide 51 text
How bind works?
(defn bind [m f]
(match m
{:error e} e
{:ok v} (f v)))
Slide 52
Slide 52 text
(defn bind [m f]
(match m
{:error e} e
{:ok v} (f v)))
How bind works?
Slide 53
Slide 53 text
How bind works?
(defn bind [m f]
(match m
{:error e} e
{:ok v} (f v)))
Slide 54
Slide 54 text
(defn bind [m f]
(match m
{:error e} e
{:ok v} (f v)))
How bind works?
Slide 55
Slide 55 text
(defn bind [m f]
(match m
{:error e} e
{:ok v} (f v)))
How bind works?
Slide 56
Slide 56 text
(defn bind [m f]
(match m
{:error e} e
{:ok v} (f v)))
How bind works?
Slide 57
Slide 57 text
Now we can compose again
(defn transact! [transaction]
(let [transaction? (bind {:ok transaction} coerce)
transaction? (bind transaction? persist!))
transaction? (bind transaction? notify!)]
transaction?))
Slide 58
Slide 58 text
Now we can compose again
(defn transact! [transaction]
(let [transaction? (bind {:ok transaction} coerce)
transaction? (bind transaction? persist!)
transaction? (bind transaction? notify!)]
transaction?))
Slide 59
Slide 59 text
We’ve just created a Monad,
and it’s called Either
There are others, like: Maybe, IO, State...
Slide 60
Slide 60 text
(defn transact! [transaction]
(-> {:ok transaction}
(bind coerce)
(bind persist!)
(bind notify!))
We can do better
Slide 61
Slide 61 text
We can do better
Libs like cats do all the hard work
https://github.com/funcool/cats
And can make our code cleaner
cats bind thread
(defn transact! [transaction]
(->= transaction
coerce
persist!
notify!))
Slide 62
Slide 62 text
What is a Monad?
Slide 63
Slide 63 text
Just a type and protocol
Slide 64
Slide 64 text
Type
type Either = {:ok value} | {:error error}
type Maybe = {:ok value} | :nothing
Slide 65
Slide 65 text
bind :: Either a -> (a -> Either b) -> Either b
return :: a -> Either a
Protocol