index edc3359..9ef23c2 100644 (file)
@@ -73,7 +73,7 @@ The **State Monad** is similar.  Once we've decided to use the following type co

Then our unit is naturally:

Then our unit is naturally:

-    let s_unit (x : 'a) : ('a state) = fun (s : store) -> (x, s)
+    let s_unit (a : 'a) : ('a state) = fun (s : store) -> (a, s)

And we can reason our way to the bind function in a way similar to the reasoning given above. First, we need to apply `f` to the contents of the `u` box:

And we can reason our way to the bind function in a way similar to the reasoning given above. First, we need to apply `f` to the contents of the `u` box:

@@ -100,7 +100,7 @@ Our other familiar monad is the **List Monad**, which we were told
looks like this:

type 'a list = ['a];;
looks like this:

type 'a list = ['a];;
-    l_unit (x : 'a) = [x];;
+    l_unit (a : 'a) = [a];;
l_bind u f = List.concat (List.map f u);;

Recall that `List.map` take a function and a list and returns the
l_bind u f = List.concat (List.map f u);;

Recall that `List.map` take a function and a list and returns the
@@ -167,7 +167,7 @@ general than an ordinary OCaml list, but we'll see how to map them
into OCaml lists soon.  We don't need to fully grasp the role of the `'b`'s
in order to proceed to build a monad:

into OCaml lists soon.  We don't need to fully grasp the role of the `'b`'s
in order to proceed to build a monad:

-    l'_unit (x : 'a) : ('a, 'b) list = fun x -> fun f z -> f x z
+    l'_unit (a : 'a) : ('a, 'b) list = fun a -> fun f z -> f a z

No problem.  Arriving at bind is a little more complicated, but
exactly the same principles apply, you just have to be careful and

No problem.  Arriving at bind is a little more complicated, but
exactly the same principles apply, you just have to be careful and
@@ -219,11 +219,48 @@ Here's a way to persuade yourself that it will have the right behavior. First, i

Now let's think about what this does. It's a wrapper around `u`. In order to behave as the list which is the result of mapping `f` over each element of `u`, and then joining (`concat`ing) the results, this wrapper would have to accept arguments `k` and `z` and fold them in just the same way that the list which is the result of mapping `f` and then joining the results would fold them. Will it?

Now let's think about what this does. It's a wrapper around `u`. In order to behave as the list which is the result of mapping `f` over each element of `u`, and then joining (`concat`ing) the results, this wrapper would have to accept arguments `k` and `z` and fold them in just the same way that the list which is the result of mapping `f` and then joining the results would fold them. Will it?

-... MORE...
+Suppose we have a list' whose contents are `[1; 2; 4; 8]`---that is, our list' will be `fun f z -> f 1 (f 2 (f 4 (f 8 z)))`. We call that list' `u`. Suppose we also have a function `f` that for each `int` we give it, gives back a list of the divisors of that `int` that are greater than 1. Intuitively, then, binding `u` to `f` should give us:

+       concat (map f u) =
+       concat [[]; ; [2; 4]; [2; 4; 8]] =
+       [2; 2; 4; 2; 4; 8]

-Our theory is that this monad should be capable of exactly
-replicating the behavior of the standard List monad.  Let's test:
+Or rather, it should give us a list' version of that, which takes a function `k` and value `z` as arguments, and returns the right fold of `k` and `z` over those elements. What does our formula
+
+      fun k z -> u (fun a b -> f a k b) z
+
+do? Well, for each element `a` in `u`, it applies `f` to that `a`, getting one of the lists:
+
+       []
+       
+       [2; 4]
+       [2; 4; 8]
+
+(or rather, their list' versions). Then it takes the accumulated result `b` of previous steps in the fold, and it folds `k` and `b` over the list generated by `f a`. The result of doing so is passed on to the next step as the accumulated result so far.
+
+So if, for example, we let `k` be `+` and `z` be `0`, then the computation would proceed:
+
+       0 ==>
+       right-fold + and 0 over [2; 4; 8] = 2+4+8+0 ==>
+       right-fold + and 2+4+8+0 over [2; 4] = 2+4+2+4+8+0 ==>
+       right-fold + and 2+4+2+4+8+0 over  = 2+2+4+2+4+8+0 ==>
+       right-fold + and 2+2+4+2+4+8+0 over [] = 2+2+4+2+4+8+0
+
+which indeed is the result of right-folding + and 0 over `[2; 2; 4; 2; 4; 8]`. If you trace through how this works, you should be able to persuade yourself that our formula:
+
+      fun k z -> u (fun a b -> f a k b) z
+
+will deliver just the same folds, for arbitrary choices of `k` and `z` (with the right types), and arbitrary list's `u` and appropriately-typed `f`s, as
+
+       fun k z -> List.fold_right k (concat (map f u)) z
+
+would.
+
+For future reference, we might make two eta-reductions to our formula, so that we have instead:
+
+      let l'_bind = fun k -> u (fun a -> f a k);;
+
+Let's make some more tests:

l_bind [1;2] (fun i -> [i, i+1]) ~~> [1; 2; 2; 3]

l_bind [1;2] (fun i -> [i, i+1]) ~~> [1; 2; 2; 3]
@@ -262,7 +299,7 @@ generalized quantifier `fun pred -> pred j` of type `(e -> t) -> t`.
Let's write a general function that will map individuals into their
corresponding generalized quantifier:

Let's write a general function that will map individuals into their
corresponding generalized quantifier:

-   gqize (x : e) = fun (p : e -> t) -> p x
+   gqize (a : e) = fun (p : e -> t) -> p a

This function wraps up an individual in a fancy box.  That is to say,
we are in the presence of a monad.  The type constructor, the unit and

This function wraps up an individual in a fancy box.  That is to say,
we are in the presence of a monad.  The type constructor, the unit and
@@ -271,16 +308,16 @@ belabor the construction of the bind function, the derivation is
similar to the List monad just given:

type 'a continuation = ('a -> 'b) -> 'b
similar to the List monad just given:

type 'a continuation = ('a -> 'b) -> 'b
-       c_unit (x : 'a) = fun (p : 'a -> 'b) -> p x
+       c_unit (a : 'a) = fun (p : 'a -> 'b) -> p a
c_bind (u : ('a -> 'b) -> 'b) (f : 'a -> ('c -> 'd) -> 'd) : ('c -> 'd) -> 'd =
c_bind (u : ('a -> 'b) -> 'b) (f : 'a -> ('c -> 'd) -> 'd) : ('c -> 'd) -> 'd =
-         fun (k : 'a -> 'b) -> u (fun (x : 'a) -> f x k)
+         fun (k : 'a -> 'b) -> u (fun (a : 'a) -> f a k)

How similar is it to the List monad?  Let's examine the type
constructor and the terms from the list monad derived above:

type ('a, 'b) list' = ('a -> 'b -> 'b) -> 'b -> 'b

How similar is it to the List monad?  Let's examine the type
constructor and the terms from the list monad derived above:

type ('a, 'b) list' = ('a -> 'b -> 'b) -> 'b -> 'b
-    l'_unit x = fun f -> f x
-    l'_bind u f = fun k -> u (fun x -> f x k)
+    l'_unit a = fun f -> f a
+    l'_bind u f = fun k -> u (fun a -> f a k)

(We performed a sneaky but valid eta reduction in the unit term.)

(We performed a sneaky but valid eta reduction in the unit term.)