diff --git a/reveal/what-makes-haskell-unique.md b/reveal/what-makes-haskell-unique.md
index e70cc66..07573d3 100644
--- a/reveal/what-makes-haskell-unique.md
+++ b/reveal/what-makes-haskell-unique.md
@@ -10,6 +10,15 @@ title: What Makes Haskell Unique
+
+
---
## Why uniqueness matters
@@ -28,10 +37,22 @@ title: What Makes Haskell Unique
* Higher order functions
* Wait... is C functional?
+
+
----
__Haskell may be functional, but that doesn't make it unique__
+
+
----
## Let's Describe Haskell
@@ -46,6 +67,14 @@ __Haskell may be functional, but that doesn't make it unique__
* Garbage collected
* Immutability
+
+
----
__It's the combination of these features that makes Haskell unique__
@@ -111,7 +140,7 @@ useJsonBodies json1 json2
----
-
+
----
@@ -121,16 +150,20 @@ useJsonBodies json1 json2
* Need to fork threads, write to mutable variables, do some locking
* Or be awesome
-```haskell
-(json1, json2) <- concurrently
+
-* Cheap green thread implementation
-* Wonderful `async` library
-* Builds on the async I/O system
+
+
Cheap green thread implementation
+
Wonderful `async` library
+
Builds on the async I/O system
+
+
+
----
@@ -152,6 +185,10 @@ promise2.andThen(|json2| =>
useJsonBody(result.get())
```
+
+
----
## Canceling in Haskell
@@ -214,7 +251,7 @@ timeout tenSeconds expensiveComputation
* Haskell differs in two ways:
* Immutable by default, explicit kind of mutability
* Mutating is an effect, tracked by the type system
-
+
----
## Mutable Haskell
@@ -243,6 +280,16 @@ let loop i =
loop 1
```
+
+
----
## Better Haskell
@@ -282,6 +329,16 @@ func printScoreRange(results: Vector) {
}
```
+
+
----
## Expected output
@@ -292,6 +349,8 @@ Highest: 55
First result was by: Alice
```
+
+
----
## What's in printScoreRange?
@@ -304,19 +363,33 @@ func printScoreRange(results: Vector) {
}
```
+
+
Actual output:
-```
-Lowest: 22
+
Lowest: 22
Highest: 55
-First result was by: Charlie
-```
+First result was by: Charlie
Non-local changes broke our guessed result
+
+
+
----
-
+
+
+
+
----
@@ -363,6 +436,8 @@ printScoreRange results = do
* Concurrent data writes? Impossible!
* We'll come back to mutable, multithreaded data
+
+
----
## Mutability when needed
@@ -374,6 +449,8 @@ printScoreRange results = do
but they're __explicit__
2. Temporary mutable copy, then freeze it
+
+
----
## Freeze!
@@ -432,6 +509,8 @@ runServer (|request| => {
})
```
+Looks reasonable, but...
+
```
Thread 1: receive request: Alice gives $25
Thread 2: receive request: Alice receives $25
@@ -441,6 +520,16 @@ Thread 1: set Alice's account to $25
Thread 2: set Alice's account to $75
```
+
+
----
## Locking
@@ -466,6 +555,8 @@ Thread 2: try to lock Alice, but can't, so wait
__Deadlock!__
+NOTE: Typical solution to this is to use locking, but it leads to other problems
+
----
## Software Transactional Memory
@@ -486,6 +577,12 @@ runServer $ \request -> atomically $ do
* `TVar` is an example of explicit mutation
* Alternatives: `IORef`, `MVar`
+NOTE:
+
+* There are helper functions to make this shorter
+* Want to make a point with the longer code
+* STM will automatically retry when needed
+
----
## The role of purity
@@ -505,6 +602,12 @@ atomically $ do
* Other side effects (like my bank account) are disallowed
* Safe for runtime to retry thanks to purity
+NOTE:
+
+* `buyBitcoins` needs to go to an exchange and spend $100,000
+* Due to retry, this code could spend $10m
+* This is where purity steps in
+
----
## Summary of STM
@@ -549,13 +652,15 @@ There are two problems with this code:
1. There's a major performance bug in it
2. It's much more cumbersome than it should be
+NOTE: Kind of cheeky to hold off on laziness this long
+
----
## Space leaks
Consider `let foo = 1 + 2`
-* `foo` isn't `3`, it's an instruction on how to create `3`
+* `foo` isn't `3`, it's an instruction for how to create `3`
* `foo` is a _thunk_ until it's evaluated
* Storing thunks is more expensive than simple types like `Int`s
* Which values are evaluated in our `loop`?
@@ -568,6 +673,13 @@ let loop i total =
in loop 1 0
```
+NOTE:
+
+* The bane of laziness is space leaks, which you may have hard
+ about. Need to understand how laziness is implemented.
+* Explain why `i` is forced and `total` is not
+* Builds a tree, lots of CPU and memory pressure
+
----
## Explicit strictness
@@ -582,9 +694,15 @@ let loop i !total =
in loop 1 0
```
-* Needing to do this is a downside of Haskell
+* Needing to do this is a downside of Haskell's laziness
* But do we get any benefits in return?
+NOTE:
+
+* Can be explicit about what needs to be evaluated
+* This is one approach, there are others
+* Just added a `!`
+
----
## Looping (1)
@@ -628,6 +746,8 @@ for(i := 1; i <= 1000000; i++) {
* Getting harder to see the forest for the trees
* If our logic was more complicated, code reuse would be an issue
+NOTE: Example of more complicated use case, writing a lookahead parser
+
----
## Some better Haskell
@@ -642,15 +762,19 @@ let loop i !total =
in loop 1 0
```
-But this is great
+
-```haskell
-sum [1..1000000]
-```
+
But this is great
-* Doesn't it allocate 8mb of ints?
-* Nope, laziness!
-* Just a thunk telling us how to get the rest of the list
+
sum [1..1000000]
+
+
+
Doesn't it allocate 8mb of ints?
+
Nope, laziness!
+
Just a thunk telling us how to get the rest of the list
+
+
+
----
@@ -671,6 +795,13 @@ sum (map (`mod` 13) (filter even [1..1000000]))
* Easy and natural to compose functions in a lazy context
* Avoids doing unnecessary work or using too much memory
+NOTE:
+
+* Never using more than a few machine words
+* Other GHC optimizations avoid allocating any thunks
+* Not covering that today
+* Mixed bag, but functional+lazy=declarative, performant
+
----
## Short circuiting for free
@@ -704,6 +835,11 @@ See also: `and`, `or`, `all`, `any`
* Also, some inefficient functions still available, `foldl` vs
`foldl'`
+NOTE:
+
+* Generally partial functions are frowned upon
+* But they're still in the language
+
----
## Summary of laziness
@@ -751,10 +887,10 @@ See also: `and`, `or`, `all`, `any`
## Parser (and other) DSLs
* Operator overloading!
-* Abstractions `Alternative` a natural fit
+* Abstractions like `Alternative` a natural fit
* `parseXMLElement <|> parseXMLText`.
* Able to reuse huge number of existing library functions,
- e.g. `optional`, `many`
+ * `optional`, `many`, `foldMap`
* General purpose `do`-notation is great
----
diff --git a/static/unique/deeper.jpg b/static/unique/deeper.jpg
new file mode 100644
index 0000000..bfd3263
Binary files /dev/null and b/static/unique/deeper.jpg differ
diff --git a/static/unique/doh.gif b/static/unique/doh.gif
new file mode 100644
index 0000000..109c4c9
Binary files /dev/null and b/static/unique/doh.gif differ