Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Monads you've already put in production (withou...
Search
Tejas Dinkar
October 10, 2014
Technology
1
1.2k
Monads you've already put in production (without knowing it)
Tejas Dinkar
October 10, 2014
Tweet
Share
More Decks by Tejas Dinkar
See All by Tejas Dinkar
Quick Wins for Page Speed
gja
0
130
Progressive Web Apps In Clojure(Script)
gja
4
2.4k
Lightning - Monads you already use (without knowing it)
gja
1
400
Native Extensions Served 3 Ways
gja
0
350
Other Decks in Technology
See All in Technology
クレジットカードの不正を防止する技術
yutadayo
16
7.3k
us-east-1 の障害が 起きると なぜ ソワソワするのか
miu_crescent
PRO
3
860
探求の技術
azukiazusa1
7
1.9k
Post-AIコーディング時代のエンジニア生存戦略
shinoyu
0
280
マイクロリブート ~ACEマインドセットで実現するアジャイル~
sony
1
340
Datadog On-Call と Cloud SIEM で作る SOC 基盤
kuriyosh
0
180
バグと向き合い、仕組みで防ぐ
____rina____
0
270
決済システムの信頼性を支える技術と運用の実践
ykagano
0
600
レビュー負債を解消する ― CodeRabbitが支えるAI駆動開発
moongift
PRO
0
250
コンピューティングリソース何を使えばいいの?
tomokusaba
1
160
それでは聞いてください「Impeller導入に失敗しました」 #FlutterKaigi #skia
tacck
PRO
0
110
AIと共に開発する時代の組織、プロセス設計 freeeでの実践から見えてきたこと
freee
3
670
Featured
See All Featured
Navigating Team Friction
lara
190
15k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Statistics for Hackers
jakevdp
799
220k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.1k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.5k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Making Projects Easy
brettharned
120
6.4k
Speed Design
sergeychernyshev
32
1.2k
Done Done
chrislema
186
16k
Building an army of robots
kneath
306
46k
Agile that works and the tools we love
rasmusluckow
331
21k
Transcript
Monads you are already using in prod Tejas Dinkar nilenso
about.me • Hi, I’m Tejas • Nilenso: Partner • twitter:
tdinkar • github: gja
Serious Pony
Online Abuse
Trouble at the Koolaid Point http://seriouspony.com/trouble-at-the-koolaid-point/ https://storify.com/adriarichards/telling-my-troll-story-because- kathy-sierra-left-t
If you think you understand Monads, you don't understand Monads.
None
This talk is inaccurate and will make a mathematician cry
None
Goal of this talk For you to say “Oh yeah,
I’ve used that hack”
None
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
None
Values Value
Monads Value Box
Mysore Masala Monad M onad Value
Monads Value Box
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
Value Value Another Value Value Function return bind
Our Function Signatures Value f(value)
Some math (√4) + 5
Some math (√4) + 5 3 or 7!
Value 4
Monad [4]
[alive, dead]
ruby! x = [1, 2, 3] y = x.map {
|x| x + 1 } # y = [2, 3, 4]
return Value Value return
return def m_return(x) [x] end # m_return(4) => [4]
The functions Value f(value)
Square Root fn def sqrt(x) s = Math.sqrt(x) [s, -s]
end # sqrt(4) => [2, -2]
Increment Fn def inc_5(x) [x + 5] end # inc_5(1)
=> [6]
Bind Functions Another Value Value Function bind
Bind Function x = m_return(4) y = x.????? { |p|
sqrt(p) } # I want [-2, 2]
Bind Function x = m_return(4) y = x.map {|p| sqrt(p)
} # y => [[2, -2]] # ^—— Box in a box?
Bind Function x = m_return(4) y = x.mapcat {|p| sqrt(p)
} # y => [2, -2]
Putting it together m_return(4) .mapcat {|p| sqrt(p)} .mapcat {|p| inc_5(p)}
# => [3, 7]
You have invented the List Monad, used to model non-determinism
Congrats
Turtles all the way down
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)
return - stays the same
bind - stays the same x = m_return(4) y =
x.mapcat { |p| inc_5(p) } # y => 9
Square Root Fn def sqrt(x) if (x < 0) return
[] #error else [Math.sqrt(x)] end end # sqrt(4) => [2] # sqrt(-1) => []
Describe in English There is a list passed to each
step Maybe this list has just one element, or Maybe it has none
None
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
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
None
Let’s start over • The Monad Laws • Left Identity
• Right Identity • Associativity
Left Identity m_return(a).bind(f) == f(a)
Right Identity m.bind(m_return) == m
Associativity m.bind(f).bind(g) == m.bind(x -> f(x).bind(g))
Store Computation
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
The functions Value f(value)
The functions (f(value) state) [new-value, new-state]
push def push(val) lambda { |state| new_state = state.push(val) [value,
new_state] } end
pop def pop() lambda { |state| val = state.pop() [val,
state] } end
def double_top() lambda { |state| top = state.pop() [2 *
top, state.push(2*top)] } end double_top
return def m_return(x) lambda { |state| [x, state] } end
bind def bind(mv, f) lambda { |state| v, temp_state =
mv(state) state_fn = f(v) state_fn(temp_state) } end
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())
None
Associativity m.bind(f).bind(g) == m.bind(x => f(x).bind(g))
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())
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())))))
done with ruby
imagine # Not working code state_monad { a <- m_return(4)
b <- push(a) c <- push(b + 1) d <- double_top() e <- sum_top2() pop() }
Back to List m_return(4) .mapcat {|p| sqrt(p)} .mapcat {|p| inc_5(p)}
# => [3, 7]
Back to List m_return(4) .mapcat {|a| sqrt(a) .mapcat {|b| inc_5(b)}}
# => [3, 7]
Back to List list_monad { a <- m_return(4) b <-
sqrt(a) c <- inc_5(b) c }
On to Clojure • this is an example from clojure.net
• the state is a vector containing every function we’ve called so far
(defn inc-s [x] (fn [state] [(inc x) (conj state :inc)]))
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]]
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)))) ])
state monad in Haskell inc = state (\st -> let
st' = st +1 in (st’,st')) inc3 = do x <- inc y <- inc z <- inc return z
Finally, IO
IOMonad • rand-int(100) is non deterministic !
ay-yo
IOMonad • rand-int(100) is non deterministic • rand-int(100, seed =
42) is deterministic • monadic value: f(world) => [value, world-after-io]
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’
Image Credits http://www.myfoodarama.com/2010/11/masala- dosa.html http://www.clojure.net/2012/02/10/State/ http://www.cafepress.com/ +no_place_like_home_ruby_slippers_3x5_area_rug, 796646161 http://www.netizens-stalbans.co.uk/installs-and- upgrades.html.htm
http://www.hpcorporategroup.com/what-is-the-life- box.html
Thank You MANY QUESTIONS? VERY MONAD SO FUNCTIONAL Y NO
CLOJURE?
[email protected]
@tdinkar WOW WOW WOW MUCH EASY SUPER SIMPLE