From: Jim Pryor Date: Mon, 13 Dec 2010 01:13:38 +0000 (-0500) Subject: rename some stuff X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=commitdiff_plain;h=434fc9bef584f51ac5338a39dc4ff5da44b5b435 rename some stuff Signed-off-by: Jim Pryor --- diff --git a/code/tree_monadize.ml b/code/tree_monadize.ml index d23606f9..43d0d981 100644 --- a/code/tree_monadize.ml +++ b/code/tree_monadize.ml @@ -10,9 +10,9 @@ module Reader_monad = struct (* change this to suit your needs *) type env = int -> int;; - type 'a monad = env -> 'a;; - let unit a : 'a monad = fun e -> a;; - let bind (u : 'a monad) (f : 'a -> 'b monad) : 'b monad = + type 'a m = env -> 'a;; + let unit a : 'a m = fun e -> a;; + let bind (u : 'a m) (f : 'a -> 'b m) : 'b m = fun e -> f (u e) e;; end @@ -20,16 +20,16 @@ module State_monad = struct (* change this to suit your needs *) type store = int;; - type 'a monad = store -> 'a * store;; - let unit a : 'a monad = fun s -> (a, s);; - let bind (u : 'a monad) (f : 'a -> 'b monad) : 'b monad = + type 'a m = store -> 'a * store;; + let unit a : 'a m = fun s -> (a, s);; + let bind (u : 'a m) (f : 'a -> 'b m) : 'b m = fun s -> (let (a, s') = u s in (f a) s');; end module List_monad = struct - type 'a monad = 'a list;; - let unit a : 'a monad = [a];; - let bind (u: 'a monad) (f : 'a -> 'b monad) : 'b monad = + type 'a m = 'a list;; + let unit a : 'a m = [a];; + let bind (u: 'a m) (f : 'a -> 'b m) : 'b m = List.concat(List.map f u);; end @@ -54,9 +54,9 @@ end * argument, or the State_monad, or another? * * There is a way to do this, but it requires putting the `... bind ...` code in - * its own module, and making that module parameterized on some X_monad + * its own module, and making that module parameterized on some M_monad * module. Also we have to explicitly declare what commonality we're expecting - * from X_monad modules we're going to use as parameters. We'll explain how to + * from M_monad modules we're going to use as parameters. We'll explain how to * do this in a moment. * * As preparation, a general observation: @@ -80,15 +80,15 @@ end * * module parameter that will choose * * whether b = list or b = option or b = reader... * * This module parameter may supply values as well as types *) - * X : sig + * M : sig * type ('a) b * end * ) = * (* A struct...end block gives a module value * * What we're doing here is building a new module that makes - * * use of the module that was supplied as X *) + * * use of the module that was supplied as M *) * struct - * type ('a) t = 'a -> ('a) X.b + * type ('a) t = 'a -> ('a) M.b * end * And here's how you'd use it: * module T_list = T_maker(struct type 'a b = 'a list end);; @@ -99,7 +99,7 @@ end * * I know, it seems unnecessarily complicated. Nonetheless, that's how it * works. And that is also the technique we'll use to make our - * `... bind ...` code parametric on some X_monad module. + * `... bind ...` code parametric on some M_monad module. *) type 'a tree = Leaf of 'a | Node of ('a tree) * ('a tree);; @@ -113,20 +113,20 @@ let t1 = Node (Leaf 7, Leaf 11)));; -module Tree_monadizer(X : sig +module Tree_monadizer(M : sig (* the module we're using as a parameter has to supply function values * for unit and bind, as well as a monadic type constructor *) - type 'a monad - val unit : 'a -> 'a monad - val bind : 'a monad -> ('a -> 'b monad) -> 'b monad + type 'a m + val unit : 'a -> 'a m + val bind : 'a m -> ('a -> 'b m) -> 'b m end) = struct - let rec monadize (t: 'a tree) (f: 'a -> 'b X.monad) : 'b tree X.monad = + let rec monadize (t: 'a tree) (f: 'a -> 'b M.monad) : 'b tree M.monad = match t with - | Leaf a -> X.bind (f a) (fun b -> X.unit (Leaf b)) + | Leaf a -> M.bind (f a) (fun b -> M.unit (Leaf b)) | Node(l, r) -> - X.bind (monadize f l) (fun l' -> - X.bind (monadize f r) (fun r' -> - X.unit (Node (l', r')))) + M.bind (monadize f l) (fun l' -> + M.bind (monadize f r) (fun r' -> + M.unit (Node (l', r')))) end;; @@ -146,31 +146,31 @@ module TreeList = Tree_monadizer(List_monad);; (* The Continuation monad is a bit more complicated *) module Continuation_monad = struct - type ('a,'r) monad = ('a -> 'r) -> 'r;; - let unit a : ('a,'r) monad = fun k -> k a;; - let bind (u: ('a,'r) monad) (f: 'a -> ('b,'r) monad) : ('b,'r) monad = + type ('r,'a) monad = ('a -> 'r) -> 'r;; + let unit a : ('r,'a) monad = fun k -> k a;; + let bind (u: ('r,'a) monad) (f: 'a -> ('r,'b) monad) : ('r,'b) monad = fun k -> u (fun a -> f a k);; end (* Since the Continuation monad is parameterized on two types---it's - * ('a,'r) cont not ('a) cont---we can't match the type ('a) monad that + * ('r,'a) cont not ('a) cont---we can't match the type ('a) monad that * Tree_monadizer expects in its parameter. So we have to make a different - * Tree_monadizer2 that takes a ('a,'z) monad type constructor in its + * Tree_monadizer2 that takes a ('r,'a) monad type constructor in its * parameter instead *) -module Tree_monadizer2(X : sig - type ('a,'z) monad - val unit : 'a -> ('a,'z) monad - val bind : ('a,'z) monad -> ('a -> ('b,'z) monad) -> ('b,'z) monad +module Tree_monadizer2(M : sig + type ('r,'a) monad + val unit : 'a -> ('r,'a) monad + val bind : ('r,'a) monad -> ('a -> ('r,'b) monad) -> ('r,'b) monad end) = struct (* the body of the monadize function is the same; the only difference is in * the types *) - let rec monadize (t: 'a tree) (f: 'a -> ('b,'x) X.monad) : ('b tree,'x) X.monad = + let rec monadize (t: 'a tree) (f: 'a -> ('r,'b) M.monad) : ('r,'b tree) M.monad = match t with - | Leaf a -> X.bind (f a) (fun b -> X.unit (Leaf b)) + | Leaf a -> M.bind (f a) (fun b -> M.unit (Leaf b)) | Node(l, r) -> - X.bind (monadize f l) (fun l' -> - X.bind (monadize f r) (fun r' -> - X.unit (Node (l', r')))) + M.bind (monadize f l) (fun l' -> + M.bind (monadize f r) (fun r' -> + M.unit (Node (l', r')))) end;; (* Make a TreeCont module containing monadize specialized to the Cont monad *) @@ -184,51 +184,51 @@ module TreeCont = Tree_monadizer2(Continuation_monad);; *) -let int_readerize : int -> int Reader_monad.monad = +let get_int : int -> int Reader_monad.monad = fun (a : int) -> fun (env : int -> int) -> env a;; -(* int_readerize takes an int and returns a Reader monad that +(* get_int takes an int and returns a Reader monad that * "looks up" that int in the environment (i.e. modifies it) * this is structurally parallel to the function `lookup` we used * before to "look up" variables in the environment *) (* double each leaf *) let env = fun i -> i + i in -TreeReader.monadize t1 int_readerize env;; +TreeReader.monadize t1 get_int env;; (* You can also avoid declaring a separate toplevel TreeReader module * (or even a separate Reader_monad module) by using one of these forms: * ... * let module T = Tree_monadizer(Reader_monad) in - * T.monadize t1 int_readerize env;; + * T.monadize t1 get_int env;; * or: * ... * let env = fun i -> i + i in * let module Monad = struct * type env = int -> int;; - * type 'a monad = env -> 'a;; - * let unit a : 'a monad = fun e -> a;; - * let bind (u : 'a monad) (f : 'a -> 'b monad) : 'b monad = + * type 'a m = env -> 'a;; + * let unit a : 'a m = fun e -> a;; + * let bind (u : 'a m) (f : 'a -> 'b m) : 'b m = * fun e -> f (u e) e;; * end in * let module T = Tree_monadizer(Monad) in - * T.monadize t1 int_readerize env;; + * T.monadize t1 get_int env;; * or: * ... * let module T = Tree_monadizer(struct * type env = int -> int;; - * type 'a monad = env -> 'a;; - * let unit a : 'a monad = fun e -> a;; - * let bind (u : 'a monad) (f : 'a -> 'b monad) : 'b monad = + * type 'a m = env -> 'a;; + * let unit a : 'a m = fun e -> a;; + * let bind (u : 'a m) (f : 'a -> 'b m) : 'b m = * fun e -> f (u e) e;; * end) in - * T.monadize t1 int_readerize env;; + * T.monadize t1 get_int env;; *) (* square each leaf *) let env = fun i -> i * i in -TreeReader.monadize t1 int_readerize env;; +TreeReader.monadize t1 get_int env;; diff --git a/manipulating_trees_with_monads.mdwn b/manipulating_trees_with_monads.mdwn index 23abaa63..35dff5d9 100644 --- a/manipulating_trees_with_monads.mdwn +++ b/manipulating_trees_with_monads.mdwn @@ -133,8 +133,8 @@ of that function. It would be a simple matter to turn an *integer* into an `int reader`: - let int_readerize : int -> int reader = fun (a : int) -> fun (modifier : int -> int) -> modifier a;; - int_readerize 2 (fun i -> i + i);; + let get_int : int -> int reader = fun (a : int) -> fun (modifier : int -> int) -> modifier a;; + get_int 2 (fun i -> i + i);; - : int = 4 But how do we do the analagous transformation when our `int`s are scattered over the leaves of a tree? How do we turn an `int tree` into a reader? @@ -185,17 +185,17 @@ Then we can expect that supplying it to our `int tree reader` will double all th In more fanciful terms, the `tree_monadize` function builds plumbing that connects all of the leaves of a tree into one connected monadic network; it threads the `'b reader` monad through the original tree's leaves. - # tree_monadize t1 int_readerize double;; + # tree_monadize t1 get_int double;; - : int tree = Node (Node (Leaf 4, Leaf 6), Node (Leaf 10, Node (Leaf 14, Leaf 22))) Here, our environment is the doubling function (`fun i -> i + i`). If we apply the very same `int tree reader` (namely, `tree_monadize -t1 int_readerize`) to a different `int -> int` function---say, the +t1 get_int`) to a different `int -> int` function---say, the squaring function, `fun i -> i * i`---we get an entirely different result: - # tree_monadize t1 int_readerize square;; + # tree_monadize t1 get_int square;; - : int tree = Node (Node (Leaf 4, Leaf 9), Node (Leaf 25, Node (Leaf 49, Leaf 121)))