X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=manipulating_trees_with_monads.mdwn;h=ba990d10b63229290fa195be8cf24c967a084593;hp=61d296405e87a62bc2cfa2e071ba8f4353fdd756;hb=23445a4f8be687dbd5be55eea7dcd7e6d2e7de05;hpb=9efbe94f74c2ea61522fcdb3e3d012fde6034fcd diff --git a/manipulating_trees_with_monads.mdwn b/manipulating_trees_with_monads.mdwn index 61d29640..ba990d10 100644 --- a/manipulating_trees_with_monads.mdwn +++ b/manipulating_trees_with_monads.mdwn @@ -13,7 +13,7 @@ From an engineering standpoint, we'll build a tree transformer that deals in monads. We can modify the behavior of the system by swapping one monad for another. We've already seen how adding a monad can add a layer of funtionality without disturbing the underlying system, for -instance, in the way that the reader monad allowed us to add a layer +instance, in the way that the Reader monad allowed us to add a layer of intensionality to an extensional grammar, but we have not yet seen the utility of replacing one monad with other. @@ -84,11 +84,11 @@ supplying the appropriate `int -> int` operation in place of `double`: Note that what `tree_map` does is take some unchanging contextual information---what to do to each leaf---and supplies that information to each subpart of the computation. In other words, `tree_map` has the -behavior of a reader monad. Let's make that explicit. +behavior of a Reader monad. Let's make that explicit. In general, we're on a journey of making our `tree_map` function more and more flexible. So the next step---combining the tree transformer with -a reader monad---is to have the `tree_map` function return a (monadized) +a Reader monad---is to have the `tree_map` function return a (monadized) tree that is ready to accept any `int -> int` function and produce the updated tree. @@ -133,10 +133,10 @@ But we can do this: let rec tree_monadize (f : 'a -> 'b reader) (t : 'a tree) : 'b tree reader = match t with - | Leaf i -> reader_bind (f i) (fun i' -> reader_unit (Leaf i')) - | Node (l, r) -> reader_bind (tree_monadize f l) (fun x -> - reader_bind (tree_monadize f r) (fun y -> - reader_unit (Node (x, y))));; + | 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'))));; This function says: give me a function `f` that knows how to turn something of type `'a` into an `'b reader`---this is a function of the same type that you could bind an `'a reader` to---and I'll show you how to @@ -190,7 +190,7 @@ result: Now that we have a tree transformer that accepts a *reader* monad as a parameter, we can see what it would take to swap in a different monad. -For instance, we can use a state monad to count the number of leaves in +For instance, we can use a State monad to count the number of leaves in the tree. type 'a state = int -> 'a * int;; @@ -203,10 +203,10 @@ modification whatsoever, except for replacing the (parametric) type let rec tree_monadize (f : 'a -> 'b state) (t : 'a tree) : 'b tree state = match t with - | Leaf i -> state_bind (f i) (fun i' -> state_unit (Leaf i')) - | Node (l, r) -> state_bind (tree_monadize f l) (fun x -> - state_bind (tree_monadize f r) (fun y -> - state_unit (Node (x, y))));; + | Leaf a -> state_bind (f a) (fun b -> state_unit (Leaf b)) + | Node (l, r) -> state_bind (tree_monadize f l) (fun l' -> + state_bind (tree_monadize f r) (fun r' -> + state_unit (Node (l', r'))));; Then we can count the number of leaves in the tree: @@ -238,7 +238,7 @@ One more revealing example before getting down to business: replacing 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. +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.