X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=manipulating_trees_with_monads.mdwn;h=c92065c41bec611a3625d6b58ac2671408646b37;hp=81dc451068072c3839e6f9e4bdf2f531011fef51;hb=f6950034eb1c228badf3364375595032a56e3afb;hpb=67cfadf1ab1d26bfa2e40ba5a675fbcdd7ea5e01 diff --git a/manipulating_trees_with_monads.mdwn b/manipulating_trees_with_monads.mdwn index 81dc4510..c92065c4 100644 --- a/manipulating_trees_with_monads.mdwn +++ b/manipulating_trees_with_monads.mdwn @@ -164,14 +164,12 @@ 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 nodes in +For instance, we can use a state monad to count the number of leaves in the tree. type 'a state = int -> 'a * int;; let state_unit a = fun s -> (a, s);; - let state_bind_and_count u f = fun s -> let (a, s') = u s in f a (s' + 1);; + let state_bind u f = fun s -> let (a, s') = u s in f a s';; Gratifyingly, we can use the `tree_monadize` function without any modification whatsoever, except for replacing the (parametric) type @@ -179,16 +177,16 @@ 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_and_count (f i) (fun i' -> state_unit (Leaf i')) - | Node (l, r) -> state_bind_and_count (tree_monadize f l) (fun x -> - state_bind_and_count (tree_monadize f r) (fun y -> + | 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))));; -Then we can count the number of nodes in the tree: +Then we can count the number of leaves in the tree: - # tree_monadize state_unit t1 0;; + # tree_monadize (fun a s -> (a, s+1)) t1 0;; - : int tree * int = - (Node (Node (Leaf 2, Leaf 3), Node (Leaf 5, Node (Leaf 7, Leaf 11))), 13) + (Node (Node (Leaf 2, Leaf 3), Node (Leaf 5, Node (Leaf 7, Leaf 11))), 5) . ___|___ @@ -201,17 +199,6 @@ Then we can count the number of nodes in the tree: | | 7 11 -Notice that we've counted each internal node twice---it's a good -exercise to adjust the code to count each node once. - - - One more revealing example before getting down to business: replacing `state` everywhere in `tree_monadize` with `list` gives us @@ -227,7 +214,7 @@ from some input to a result, this transformer replaces each `int` with a list of `int`'s. @@ -252,8 +239,6 @@ We then compute: # tree_monadize (fun a k -> a :: (k a)) t1 (fun t -> []);; - : int list = [2; 3; 5; 7; 11] - - We have found a way of collapsing a tree into a list of its leaves. The continuation monad is amazingly flexible; we can use it to @@ -290,6 +275,9 @@ generalizing the type of the continuation monad to type ('a, 'b, 'c) continuation = ('a -> 'b) -> 'c;; +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). + + The binary tree monad ---------------------