Slide 1

Slide 1 text

Fun Monads with

Slide 2

Slide 2 text

Marcelo Piva Software Engineer @ Nubank @mpivaa github.com/mpivaa instagram.com/m.pivaa

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Monads

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

“Monads are just monoids in the category of endofunctors”

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

Why do we need Monads?

Slide 11

Slide 11 text

Why do we need Monads? We want to use only functions. We want to use pure functions. We want to compose functions.

Slide 12

Slide 12 text

Class Object Instance Inheritance Polymorphism Abstract Factory Builder Factory Method Object Pool Prototype Singleton Adapter Bridge Composite Decorator Facade Flyweight Private Class Data Proxy Chain of responsibility Command Interpreter Iterator Mediator Memento Null Object Observer State

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Why do we need Monads? We want to use only functions. We want to use pure functions. We want to compose functions.

Slide 15

Slide 15 text

Why do we need Monads? We want to use only functions. We want to use pure functions. We want to compose functions.

Slide 16

Slide 16 text

Imperative mindset 1. a = do_a(x) 2. b = do_b(a) 3. if b 4. do_c(b)

Slide 17

Slide 17 text

Functional mindset do!(c(b(a(x))))

Slide 18

Slide 18 text

Functional mindset do!(c(b(a(x))))

Slide 19

Slide 19 text

Functional mindset do!(c(b(a(x))))

Slide 20

Slide 20 text

Functional mindset do!(c(b(a(x))))

Slide 21

Slide 21 text

Functional mindset do!(c(b(a(x))))

Slide 22

Slide 22 text

a Composing functions b c do!

Slide 23

Slide 23 text

Imperative public class TransactionRequest { public static String transact(Request request) { Transaction transaction = coerce(request); transaction = persist(transaction); notify(transaction); } }

Slide 24

Slide 24 text

Imperative public class TransactionRequest { public static String transact(Request request) { Transaction transaction = coerce(request); transaction = persist(transaction); notify(transaction); } }

Slide 25

Slide 25 text

Functional (defn transact! [transaction] (notify! (persist! (coerce transaction))))

Slide 26

Slide 26 text

Functional (defn transact! [transaction] (-> transaction coerce persist! notify!))

Slide 27

Slide 27 text

Functional (defn transact! [transaction] (-> transaction coerce persist! notify!))

Slide 28

Slide 28 text

Imperative Functional public class TransactionRequest { public static String transact(Request request) { Transaction transaction = coerce(request); transaction = persist(transaction); notify(transaction); } } (defn transaction! [transaction] (-> transaction coerce persist! notify!))

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Imperative Functional public class TransactionRequest { public static String transact(Request request) { Transaction transaction = coerce(request); transaction = persist(transaction); notify(transaction); } } (defn transaction! [transaction] (-> transaction coerce persist! notify!)) NullPointerException

Slide 31

Slide 31 text

Imperative Functional public class TransactionRequest { public static String transact(Request request) { Transaction transaction = coerce(request); transaction = persist(transaction); notify(transaction); } } (defn transaction! [transaction] (-> transaction coerce persist! notify!)) NullPointerException

Slide 32

Slide 32 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); } }

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); } }

Slide 35

Slide 35 text

We need to handle errors

Slide 36

Slide 36 text

We need to handle errors public static String transact(Request request) { try { Transaction transaction = coerce(request); } catch (Exception e) { return "Error adapting request"; } try { transaction = persist(transaction); if(!transaction) { return "Error persisting transaction"; } } catch(DBError e) { return "DB Error"; } try { if(!notify(transaction)) { return "Error notifying transaction"; } } catch(SMTPError e) { return "SMTP Error"; } return "OK"; }

Slide 37

Slide 37 text

public static String transact(Request request) { try { Transaction transaction = coerce(request); } catch (Exception e) { return "Error adapting request"; } try { transaction = persist(transaction); if(!transaction) { return "Error persisting transaction"; } } catch(DBError e) { return "DB Error"; } try { if(!notify(transaction)) { return "Error notifying transaction"; } } catch(SMTPError e) { return "SMTP Error"; } return "OK"; } We need to handle errors

Slide 38

Slide 38 text

public static String transact(Request request) { try { Transaction transaction = coerce(request); } catch (Exception e) { return "Error adapting request"; } try { transaction = persist(transaction); if(!transaction) { return "Error persisting transaction"; } } catch(DBError e) { return "DB Error"; } try { if(!notify(transaction)) { return "Error notifying transaction"; } } catch(SMTPError e) { return "SMTP Error"; } return "OK"; } We need to handle errors

Slide 39

Slide 39 text

We need to handle errors

Slide 40

Slide 40 text

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

Slide 66

Slide 66 text

Monads everywhere?

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

Thanks! We're hiring! https://nubank.workable.com/ https://t.me/clojurebrasil @mpivaa github.com/mpivaa instagram.com/m.pivaa