diff --git a/content/blog/coq_dawn_eval.md b/content/blog/coq_dawn_eval.md
index 3af286d..58890a0 100644
--- a/content/blog/coq_dawn_eval.md
+++ b/content/blog/coq_dawn_eval.md
@@ -265,10 +265,61 @@ eval_chain nil (e_comp (e_comp true false) or) (true :: nil)
This is the type of sequences (or chains) of steps corresponding to the
evaluation of the program \\(\\text{true}\\ \\text{false}\\ \\text{or}\\),
-starting in an empty stack and evaluating to a stack with only true on top.
-Thus to say that an expression evaluates to some final stack `vs'`, in
-_some unknown number of steps_, it's sufficient to write:
+starting in an empty stack and evaluating to a stack with only
+\\(\\text{true}\\) on top. Thus to say that an expression evaluates to some
+final stack `vs'`, in _some unknown number of steps_, it's sufficient to write:
```Coq
eval_chain vs e vs'
```
+
+Evaluation chains have a couple of interesting properties. First and foremost,
+they can be "concatenated". This is analagous to the `Sem_e_comp` rule
+in our original semantics: if an expression `e1` starts in stack `vs`
+and finishes in stack `vs'`, and another expression starts in stack `vs'`
+and finishes in stack `vs''`, then we can compose these two expressions,
+and the result will start in `vs` and finish in `vs''`.
+
+{{< codelines "Coq" "dawn/DawnEval.v" 69 75 >}}
+
+The proof is very short. We go
+{{< sidenote "right" "concat-note" "by induction on the left evaluation" >}}
+It's not a coincidence that defining something like (++)
+(list concatenation) in Haskell typically starts by pattern matching
+on the left list. In fact, proofs by induction
+actually correspond to recursive functions! It's tough putting code blocks
+in sidenotes, but if you're playing with the
+DawnEval.v
file, try running
+Print eval_chain_ind
, and note the presence of fix
,
+the fixed point
+combinator used to implement recursion.
+{{< /sidenote >}}
+chain (the one for `e1`). Coq takes care of most of the rest with `auto`.
+The key to this proof is that whatever `P` is cotained within a "node"
+in the left chain determines how `eval_step (e_comp e1 e2)` behaves. Whether
+`e1` evaluates to `final` or `middle`, the composition evaluates to `middle`
+(a composition of two expressions cannot be done in one step), so we always
+{{< sidenote "left" "cons-note" "create a new \"cons\" node." >}}
+This is unlike list concatenation, since we typically don't
+create new nodes when appending to an empty list.
+{{< /sidenote >}} via `chain_middle`. Then, the two cases are as follows:
+
+* If the step was `final`, then
+ the rest of the steps use only `e2`, and good news, we already have a chain
+ for that!
+* Otherwise, the step was `middle`, an we stll have a chain for some
+ intermediate program `ei` that starts in some stack `vsi` and ends in `vs'`.
+ By induction, we know that _this_ chain can be concatenated with the one
+ for `e2`, resulting in a chain for `e_comp ei e2`. All that remains is to
+ attach to this sub-chain the one step from `(vs, e1)` to `(vsi, ei)`, which
+ is handled by `chain_middle`.
+
+ {{< todo >}}A drawing would be nice here!{{< /todo >}}
+
+The `merge` operation is reversible; chains can be split into two pieces,
+one for each composed expression:
+
+{{< codelines "Coq" "dawn/DawnEval.v" 77 78 >}}
+
+While interesting, this particular fact isn't used anywhere else in this
+post, and I will omit the proof here.