Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Monads you've already put in production (without knowing it)

Monads you've already put in production (without knowing it)

Tejas Dinkar

October 10, 2014
Tweet

More Decks by Tejas Dinkar

Other Decks in Technology

Transcript

  1. Monads • Programmable Semicolons • Used to hide plumbing away

    from you • You can say Monads in almost any sentence and people will think you are smart
  2. Monads • Monads define two functions • return takes a

    value and puts it in a box • bind takes a box & function f, returning f(value) • it is expected that the function returns a box
  3. ruby! x = [1, 2, 3] y = x.map {

    |x| x + 1 } # y = [2, 3, 4]
  4. Bind Function x = m_return(4) y = x.map {|p| sqrt(p)

    } # y => [[2, -2]] # ^—— Box in a box?
  5. A small constraint • Let’s do a bit of a

    self imposed constraint on this • Functions must return either 0 or 1 elements • (we’ll only model positive integers here)
  6. bind - stays the same x = m_return(4) y =

    x.mapcat { |p| inc_5(p) } # y => 9
  7. Square Root Fn def sqrt(x) if (x < 0) return

    [] #error else [Math.sqrt(x)] end end # sqrt(4) => [2] # sqrt(-1) => []
  8. Describe in English There is a list passed to each

    step Maybe this list has just one element, or Maybe it has none
  9. The Maybe Monad • The intent is to short circuit

    computation • The value of the `box’ is None, or Just(Value) • You can think of it as a type-safe nil / null
  10. try def try(x, f) if x == nil return f(x)

    else return nil end end # 4.try { |x| x + 5 } => 9 # nil.try {|x| x + 5 } => nil
  11. Let’s start over • The Monad Laws • Left Identity

    • Right Identity • Associativity
  12. The State Monad • Rest of the world - State

    Machine (sorta) • The value inside the box f(state) => [r new-state] • Particularly useful in pure languages like Haskell • Let’s build a stack
  13. def double_top() lambda { |state| top = state.pop() [2 *

    top, state.push(2*top)] } end double_top
  14. bind def bind(mv, f) lambda { |state| v, temp_state =

    mv(state) state_fn = f(v) state_fn(temp_state) } end
  15. example # Not working code ! m_return(4) .bind(a -> push(a))

    .bind(b -> push(b + 1)) .bind(c -> double_top()) .bind(d -> sum_top2()) .bind(e -> pop())
  16. turn this # Not working code ! m_return(4) .bind(a ->

    push(a)) .bind(b -> push(b + 1)) .bind(c -> double_top()) .bind(d -> sum_top2()) .bind(e -> pop())
  17. into this m_return(4) .bind(a -> push(a) .bind(b -> push(b +

    1) .bind(c -> double_top() .bind(d -> sum_top() .bind(e -> pop())))))
  18. imagine # Not working code state_monad { a <- m_return(4)

    b <- push(a) c <- push(b + 1) d <- double_top() e <- sum_top2() pop() }
  19. On to Clojure • this is an example from clojure.net

    • the state is a vector containing every function we’ve called so far
  20. in clojure (defn inc-s [x] (fn [state] [(inc x) (conj

    state :inc)])) (defn do-things [x] (domonad state-m [a (inc-s x) b (double-s a) c (dec-s b) d (dec-s c)] d)) ! ((do-things 7) []) => [14 [:inc :double :dec :dec]]
  21. state monad in Clojure (defmonad state-m "Monad describing stateful computations.

    The monadic values have the structure (fn [old-state] [result new-state])." [m-result (fn m-result-state [v] (fn [s] [v s])) m-bind (fn m-bind-state [mv f] (fn [s] (let [[v ss] (mv s)] ((f v) ss)))) ])
  22. state monad in Haskell inc = state (\st -> let

    st' = st +1 in (st’,st')) inc3 = do x <- inc y <- inc z <- inc return z
  23. IOMonad • rand-int(100) is non deterministic • rand-int(100, seed =

    42) is deterministic • monadic value: f(world) => [value, world-after-io]
  24. IOMonad • puts() just `appends to a buffer’ in the

    real world • How does gets() return different strings? • gets() returns a fixed value based on the `world’
  25. Thank You MANY QUESTIONS? VERY MONAD SO FUNCTIONAL Y NO

    CLOJURE? [email protected] @tdinkar WOW WOW WOW MUCH EASY SUPER SIMPLE