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
Slide 6
Slide 6 text
If you think you understand Monads,
you don't understand Monads.
Slide 7
Slide 7 text
No content
Slide 8
Slide 8 text
This talk is inaccurate and will
make a mathematician cry
Slide 9
Slide 9 text
No content
Slide 10
Slide 10 text
Goal of this talk
For you to say
“Oh yeah, I’ve used that hack”
Slide 11
Slide 11 text
No content
Slide 12
Slide 12 text
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
Slide 13
Slide 13 text
No content
Slide 14
Slide 14 text
Values
Value
Slide 15
Slide 15 text
Monads
Value
Box
Slide 16
Slide 16 text
Mysore Masala Monad
M
onad
Value
Slide 17
Slide 17 text
Monads
Value
Box
Slide 18
Slide 18 text
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
Slide 19
Slide 19 text
Value Value
Another Value
Value
Function
return
bind
Slide 20
Slide 20 text
Our Function Signatures
Value
f(value)
Slide 21
Slide 21 text
Some math
(√4) + 5
Slide 22
Slide 22 text
Some math
(√4) + 5
3 or 7!
Slide 23
Slide 23 text
Value
4
Slide 24
Slide 24 text
Monad
[4]
Slide 25
Slide 25 text
[alive, dead]
Slide 26
Slide 26 text
ruby!
x = [1, 2, 3]
y = x.map { |x|
x + 1
}
# y = [2, 3, 4]
Slide 27
Slide 27 text
return
Value Value
return
Slide 28
Slide 28 text
return
def m_return(x)
[x]
end
# m_return(4)
=> [4]
Slide 29
Slide 29 text
The functions
Value
f(value)
Slide 30
Slide 30 text
Square Root fn
def sqrt(x)
s = Math.sqrt(x)
[s, -s]
end
# sqrt(4) => [2, -2]
Bind Function
x = m_return(4)
y = x.????? { |p|
sqrt(p)
}
# I want [-2, 2]
Slide 34
Slide 34 text
Bind Function
x = m_return(4)
y = x.map {|p|
sqrt(p)
}
# y => [[2, -2]]
# ^—— Box in a
box?
Slide 35
Slide 35 text
Bind Function
x = m_return(4)
y = x.mapcat {|p|
sqrt(p)
}
# y => [2, -2]
Slide 36
Slide 36 text
Putting it together
m_return(4)
.mapcat {|p| sqrt(p)}
.mapcat {|p|
inc_5(p)}
# => [3, 7]
Slide 37
Slide 37 text
You have invented the
List Monad, used to
model non-determinism
Congrats
Slide 38
Slide 38 text
Turtles all the way down
Slide 39
Slide 39 text
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)
Slide 40
Slide 40 text
return - stays the same
Slide 41
Slide 41 text
bind - stays the same
x = m_return(4)
y = x.mapcat { |p|
inc_5(p)
}
# y => 9
Slide 42
Slide 42 text
Square Root Fn
def sqrt(x)
if (x < 0)
return [] #error
else
[Math.sqrt(x)]
end
end
# sqrt(4) => [2]
# sqrt(-1) => []
Slide 43
Slide 43 text
Describe in English
There is a list passed to each step
Maybe this list has just one element,
or Maybe it has none
Slide 44
Slide 44 text
No content
Slide 45
Slide 45 text
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
Slide 46
Slide 46 text
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
Slide 47
Slide 47 text
No content
Slide 48
Slide 48 text
Let’s start over
• The Monad Laws
• Left Identity
• Right Identity
• Associativity
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
Slide 54
Slide 54 text
The functions
Value
f(value)
Slide 55
Slide 55 text
The functions
(f(value) state) [new-value, new-state]
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())
Slide 65
Slide 65 text
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())))))
Slide 66
Slide 66 text
done with ruby
Slide 67
Slide 67 text
imagine
# Not working code
state_monad {
a <- m_return(4)
b <- push(a)
c <- push(b + 1)
d <- double_top()
e <- sum_top2()
pop()
}
Slide 68
Slide 68 text
Back to List
m_return(4)
.mapcat {|p| sqrt(p)}
.mapcat {|p|
inc_5(p)}
# => [3, 7]
Slide 69
Slide 69 text
Back to List
m_return(4)
.mapcat {|a| sqrt(a)
.mapcat {|b|
inc_5(b)}}
# => [3, 7]
Slide 70
Slide 70 text
Back to List
list_monad {
a <- m_return(4)
b <- sqrt(a)
c <- inc_5(b)
c
}
Slide 71
Slide 71 text
On to Clojure
• this is an example from clojure.net
• the state is a vector containing every function
we’ve called so far
Slide 72
Slide 72 text
(defn inc-s [x]
(fn [state]
[(inc x) (conj state :inc)]))
Slide 73
Slide 73 text
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]]
Slide 74
Slide 74 text
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))))
])
Slide 75
Slide 75 text
state monad in Haskell
inc = state
(\st -> let st' = st +1
in (st’,st'))
inc3 = do x <- inc
y <- inc
z <- inc
return z
Slide 76
Slide 76 text
Finally, IO
Slide 77
Slide 77 text
IOMonad
• rand-int(100) is non deterministic
!
Slide 78
Slide 78 text
ay-yo
Slide 79
Slide 79 text
IOMonad
• rand-int(100) is non deterministic
• rand-int(100, seed = 42) is deterministic
• monadic value: f(world) => [value, world-after-io]
Slide 80
Slide 80 text
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’