Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
140
Progressive Web Apps In Clojure(Script)
gja
4
2.4k
Lightning - Monads you already use (without knowing it)
gja
1
410
Native Extensions Served 3 Ways
gja
0
360
Other Decks in Technology
See All in Technology
20251222_サンフランシスコサバイバル術
ponponmikankan
2
130
Lookerで実現するセキュアな外部データ提供
zozotech
PRO
0
190
.NET 10の概要
tomokusaba
0
130
Amazon Bedrock Knowledge Bases × メタデータ活用で実現する検証可能な RAG 設計
tomoaki25
6
1.9k
Identity Management for Agentic AI 解説
fujie
0
330
AWSに革命を起こすかもしれない新サービス・アップデートについてのお話
yama3133
0
450
MariaDB Connector/C のcaching_sha2_passwordプラグインの仕様について
boro1234
0
990
Databricks向けJupyter Kernelでデータサイエンティストの開発環境をAI-Readyにする / Data+AI World Tour Tokyo After Party
genda
1
630
Kiro を用いたペアプロのススメ
taikis
4
1.4k
IAMユーザーゼロの運用は果たして可能なのか
yama3133
2
520
意外と知らない状態遷移テストの世界
nihonbuson
PRO
1
130
高度サイバー人材育成専科資料(前半)
nomizone
0
370
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
How to make the Groovebox
asonas
2
1.8k
The agentic SEO stack - context over prompts
schlessera
0
550
Building Flexible Design Systems
yeseniaperezcruz
330
39k
How Software Deployment tools have changed in the past 20 years
geshan
0
29k
How to train your dragon (web standard)
notwaldorf
97
6.4k
We Have a Design System, Now What?
morganepeng
54
7.9k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
2
250
Making the Leap to Tech Lead
cromwellryan
135
9.7k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
0
3.3k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
320
Embracing the Ebb and Flow
colly
88
4.9k
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