XGitUrl: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=manipulating_trees_with_monads.mdwn;h=2ec15d6a6c9a8ee37ec39304a5f4d1ee75befffc;hp=16097633b0a1aff14e82643ad777c2577d385a58;hb=9fe62083953213cce34fc4458e36666902c5ee4b;hpb=008afaa826fadb5feab482b89d798903004a7b63
diff git a/manipulating_trees_with_monads.mdwn b/manipulating_trees_with_monads.mdwn
index 16097633..2ec15d6a 100644
 a/manipulating_trees_with_monads.mdwn
+++ b/manipulating_trees_with_monads.mdwn
@@ 3,11 +3,13 @@
Manipulating trees with monads

This topic develops an idea based on a detailed suggestion of Ken
Shan's. We'll build a series of functions that operate on trees,
doing various things, including replacing leaves, counting nodes, and
converting a tree to a list of leaves. The end result will be an
application for continuations.
+This topic develops an idea based on a suggestion of Ken Shan's.
+We'll build a series of functions that operate on trees, doing various
+things, including updating leaves with a Reader monad, counting nodes
+with a State monad, replacing leaves with a List monad, and converting
+a tree into a list of leaves with a Continuation monad. It will turn
+out that the continuation monad can simulate the behavior of each of
+the other monads.
From an engineering standpoint, we'll build a tree transformer that
deals in monads. We can modify the behavior of the system by swapping
@@ 20,7 +22,7 @@ the utility of replacing one monad with other.
First, we'll be needing a lot of trees for the remainder of the
course. Here again is a type constructor for leaflabeled, binary trees:
 type 'a tree = Leaf of 'a  Node of ('a tree * 'a tree)
+ type 'a tree = Leaf of 'a  Node of ('a tree * 'a tree);;
[How would you adjust the type constructor to allow for labels on the
internal nodes?]
@@ 30,7 +32,7 @@ We'll be using trees where the nodes are integers, e.g.,
let t1 = Node (Node (Leaf 2, Leaf 3),
Node (Leaf 5, Node (Leaf 7,
 Leaf 11)))
+ Leaf 11)))
.
______
 
@@ 71,14 +73,15 @@ structure of the tree unchanged. For instance:
14 22
We could have built the doubling operation right into the `tree_map`
code. However, because we've left what to do to each leaf as a parameter, we can
decide to do something else to the leaves without needing to rewrite
`tree_map`. For instance, we can easily square each leaf instead by
supplying the appropriate `int > int` operation in place of `double`:
+code. However, because we've made what to do to each leaf a
+parameter, we can decide to do something else to the leaves without
+needing to rewrite `tree_map`. For instance, we can easily square
+each leaf instead by supplying the appropriate `int > int` operation
+in place of `double`:
let square i = i * i;;
tree_map square t1;;
  : int tree =ppp
+  : int tree =
Node (Node (Leaf 4, Leaf 9), Node (Leaf 25, Node (Leaf 49, Leaf 121)))
Note that what `tree_map` does is take some unchanging contextual
@@ 106,14 +109,25 @@ updated tree.
f 7 f 11
That is, we want to transform the ordinary tree `t1` (of type `int
tree`) into a reader object of type `(int > int) > int tree`: something
that, when you apply it to an `int > int` function `f` returns an `int
tree` in which each leaf `i` has been replaced with `f i`.

With previous readers, we always knew which kind of environment to
expect: either an assignment function (the original calculator
simulation), a world (the intensionality monad), an integer (the
Jacobsoninspired link monad), etc. In the present case, we expect that our "environment" will be some function of type `int > int`. "Looking up" some `int` in the environment will return us the `int` that comes out the other side of that function.
+tree`) into a reader monadic object of type `(int > int) > int
+tree`: something that, when you apply it to an `int > int` function
+`f` returns an `int tree` in which each leaf `i` has been replaced
+with `f i`.
+
+[Application note: this kind of reader object could provide a model
+for Kaplan's characters. It turns an ordinary tree into one that
+expects contextual information (here, the `λ f`) that can be
+used to compute the content of indexicals embedded arbitrarily deeply
+in the tree.]
+
+With our previous applications of the Reader monad, we always knew
+which kind of environment to expect: either an assignment function, as
+in the original calculator simulation; a world, as in the
+intensionality monad; an individual, as in the Jacobsoninspired link
+monad; etc. In the present case, we expect that our "environment"
+will be some function of type `int > int`. "Looking up" some `int` in
+the environment will return us the `int` that comes out the other side
+of that function.
type 'a reader = (int > int) > 'a;; (* mnemonic: e for environment *)
let reader_unit (a : 'a) : 'a reader = fun _ > a;;
@@ 218,14 +232,52 @@ Then we can count the number of leaves in the tree:
______
 
. .
 ___ ___
+ ___ ___ , 5
   
2 3 5 .
___
 
7 11
Why does this work? Because the operation `fun a > fun s > (a, s+1)` takes an `int` and wraps it in an `int state` monadic box that increments the state. When we give that same operations to our `tree_monadize` function, it then wraps an `int tree` in a box, one that does the same stateincrementing for each of its leaves.
+Note that the value returned is a pair consisting of a tree and an
+integer, 5, which represents the count of the leaves in the tree.
+
+Why does this work? Because the operation `fun a > fun s > (a, s+1)`
+takes an `int` and wraps it in an `int state` monadic box that
+increments the state. When we give that same operations to our
+`tree_monadize` function, it then wraps an `int tree` in a box, one
+that does the same stateincrementing for each of its leaves.
+
+We can use the state monad to replace leaves with a number
+corresponding to that leave's ordinal position. When we do so, we
+reveal the order in which the monadic tree forces evaluation:
+
+ # tree_monadize (fun a > fun s > (s+1, s+1)) t1 0;;
+  : int tree * int =
+ (Node (Node (Leaf 1, Leaf 2), Node (Leaf 3, Node (Leaf 4, Leaf 5))), 5)
+
+The key thing to notice is that instead of copying `a` into the
+monadic box, we throw away the `a` and put a copy of the state in
+instead.
+
+Reversing the order requires reversing the order of the state_bind
+operations. It's not obvious that this will type correctly, so think
+it through:
+
+ let rec tree_monadize_rev (f : 'a > 'b state) (t : 'a tree) : 'b tree state =
+ match t with
+  Leaf a > state_bind (f a) (fun b > state_unit (Leaf b))
+  Node (l, r) > state_bind (tree_monadize f r) (fun r' >
+ state_bind (tree_monadize f l) (fun l' >
+ state_unit (Node (l', r'))));;
+
+ # tree_monadize_rev (fun a > fun s > (s+1, s+1)) t1 0;;
+  : int tree * int =
+ (Node (Node (Leaf 5, Leaf 4), Node (Leaf 3, Node (Leaf 2, Leaf 1))), 5)
+
+We will need below to depend on controlling the order in which nodes
+are visited when we use the continuation monad to solve the
+samefringe problem.
One more revealing example before getting down to business: replacing
`state` everywhere in `tree_monadize` with `list` gives us
@@ 240,11 +292,11 @@ Unlike the previous cases, instead of turning a tree into a function
from some input to a result, this transformer replaces each `int` with
a list of `int`'s. We might also have done this with a Reader monad, though then our environments would need to be of type `int > int list`. Experiment with what happens if you supply the `tree_monadize` based on the List monad an operation like `fun > [ i; [2*i; 3*i] ]`. Use small trees for your experiment.



+[Why is the argument to `tree_monadize` `int > int list list` instead
+of `int > int list`? Well, as usual, the List monad bind operation
+will erase the outer list box, so if we want to replace the leaves
+with lists, we have to nest the replacement lists inside a disposable
+box.]
Now for the main point. What if we wanted to convert a tree to a list
of leaves?
@@ 306,12 +358,37 @@ generalizing the type of the Continuation monad to
If you want to see how to parameterize the definition of the `tree_monadize` function, so that you don't have to keep rewriting it for each new monad, see [this code](/code/tree_monadize.ml).
+Using continuations to solve the same fringe problem
+
+
+We've seen two solutions to the same fringe problem so far.
+The simplest is to map each tree to a list of its leaves, then compare
+the lists. But if the fringes differ in an early position, we've
+wasted our time visiting the rest of the tree.
+
+The second solution was to use tree zippers and mutable state to
+simulate coroutines. We would unzip the first tree until we found the
+next leaf, then store the zipper structure in the mutable variable
+while we turned our attention to the other tree. Because we stop as
+soon as we find the first mismatched leaf, this solution does not have
+the flaw just mentioned of the solution that maps both trees to a list
+of leaves before beginning comparison.
+
+Since zippers are just continuations reified, we expect that the
+solution in terms of zippers can be reworked using continuations, and
+this is indeed the case. To make this work in the most convenient
+way, we need to use the fully general type for continuations just mentioned.
+
+tree_monadize (fun a k > a, k a) t1 (fun t > 0);;
+
+
The Binary Tree monad

Of course, by now you may have realized that we have discovered a new
monad, the Binary Tree monad:
+monad, the Binary Tree monad. Just as mere lists are in fact a monad,
+so are trees. Here is the type constructor, unit, and bind:
type 'a tree = Leaf of 'a  Node of ('a tree) * ('a tree);;
let tree_unit (a: 'a) : 'a tree = Leaf a;;
@@ 397,7 +474,7 @@ that is intended to represent nondeterministic computations as a tree.
What's this have to do with tree\_mondadize?

So we've defined a Tree monad
+So we've defined a Tree monad:
type 'a tree = Leaf of 'a  Node of ('a tree) * ('a tree);;
let tree_unit (a: 'a) : 'a tree = Leaf a;;
@@ 417,112 +494,5 @@ What's this have to do with the `tree_monadize` functions we defined earlier?
... and so on for different monads?
The answer is that each of those `tree_monadize` functions is adding a Tree monad *layer* to a preexisting Reader (and so on) monad. So far, we've defined monads as singlelayered things. (Though in the Groenendijk, Stokhoff, and Veltmann application, we had to figure out how to combine Reader, State, and Set monads in an adhoc way.) But in practice, one often wants to combine the abilities of several monads. Corresponding to each monad like Reader, there's a corresponding ReaderT **monad transformer**. That takes an existing monad M and adds a Reader monad layer to it. The way these are defined parallels the way the singlelayer versions are defined. For example, here's the Reader monad:

 (* monadic operations for the Reader monad *)

 type 'a reader =
 env > 'a;;
 let unit (a : 'a) : 'a reader =
 fun e > a;;
 let bind (u: 'a reader) (f : 'a > 'b reader) : 'b reader =
 fun e > (fun v > f v e) (u e);;

We've just betaexpanded the familiar `f (u e) e` into `(fun v > f v e) (u e)` to factor out the parts where any Reader monad is being supplied as an argument to another function. Then if we want instead to add a Reader layer to some arbitrary other monad M, with its own M.unit and M.bind, here's how we do it:

 (* monadic operations for the ReaderT monadic transformer *)

 (* We're not giving valid OCaml code, but rather something
 * that's conceptually easier to digest.
 * How you really need to write this in OCaml is more circuitious...
 * see http://lambda.jimpryor.net/code/tree_monadize.ml for some details. *)

 type ('a, M) readerT =
 env > 'a M;;
 (* this is just an 'a M reader; but that doesn't generalize *)

 let unit (a : 'a) : ('a, M) readerT =
 fun e > M.unit a;;

 let bind (u : ('a, M) readerT) (f : 'a > ('b, M) readerT) : ('b, M) readerT =
 fun e > M.bind (u e) (fun v > f v e);;

Notice the key differences: where before we just returned `a`, now we return `M.unit a`. Where before we just supplied a value `u e` of type `'a reader` as an argument to a function, now we instead `M.bind` the `'a reader` to that function. Notice also the differences in the types.

What is the relation between Reader and ReaderT? Well, suppose you started with the Identity monad:

 type 'a identity = 'a;;
 let unit (a : 'a) : 'a = a;;
 let bind (u : 'a) (f : 'a > 'b) : 'b = f u;;

and you used the ReaderT transformer to add a Reader monad layer to the Identity monad. What do you suppose you would get?

The relations between the State monad and the StateT monadic transformer are parallel:

 (* monadic operations for the State monad *)

 type 'a state =
 store > ('a * store);;

 let unit (a : 'a) : 'a state =
 fun s > (a, s);;

 let bind (u : 'a state) (f : 'a > 'b state) : 'b state =
 fun s > (fun (a, s') > f a s') (u s);;

We've used `(fun (a, s') > f a s') (u s)` instead of the more familiar `let (a, s') = u s in f a s'` in order to factor out the part where a value of type `'a state` is supplied as an argument to a function. Now StateT will be:

 (* monadic operations for the StateT monadic transformer *)

 type ('a, M) stateT =
 store > ('a * store) M;;
 (* notice this is not an 'a M state *)

 let unit (a : 'a) : ('a, M) stateT =
 fun s > M.unit (a, s);;

 let bind (u : ('a, M) stateT) (f : 'a > ('b, M) stateT) : ('b, M) stateT =
 fun s > M.bind (u s) (fun (a, s') > f a s');;

Do you see the pattern? Where ordinarily we'd return an `'a` value, now we instead return an `'a M` value. Where ordinarily we'd supply a `'a state` value as an argument to a function, now we instead `M.bind` it to that function.

Okay, now let's do the same thing for our Tree monad.

 (* monadic operations for the Tree monad *)

 type 'a tree =
 Leaf of 'a  Node of ('a tree) * ('a tree);;

 let unit (a: 'a) : 'a tree =
 Leaf a;;

 let rec bind (u : 'a tree) (f : 'a > 'b tree) : 'b tree =
 match u with
  Leaf a > f a
  Node (l, r) > (fun l' r' > Node (l', r')) (bind l f) (bind r f);;

 (* monadic operations for the TreeT monadic transformer *)

 type ('a, M) treeT =
 'a tree M;;

 let unit (a: 'a) : ('a, M) tree =
 M.unit (Leaf a);;

 let rec bind (u : ('a, M) tree) (f : 'a > ('b, M) tree) : ('b, M) tree =
 match u with
  Leaf a > M.unit (f a)
  Node (l, r) > M.bind (bind l f) (fun l' >
 M.bind (bind r f) (fun r' >
 M.unit (Node (l', r'));;

Compare this definition of `bind` for the TreeT monadic transformer to our earlier definition of `tree_monadize`, specialized for the Reader monad:

 let rec tree_monadize (f : 'a > 'b reader) (t : 'a tree) : 'b tree reader =
 match t with
  Leaf a > reader_bind (f a) (fun b > reader_unit (Leaf b))
  Node (l, r) > reader_bind (tree_monadize f l) (fun l' >
 reader_bind (tree_monadize f r) (fun r' >
 reader_unit (Node (l', r'))));;

+The answer is that each of those `tree_monadize` functions is adding a Tree monad *layer* to a preexisting Reader (and so on) monad. We discuss that further here: [[Monad Transformers]].