+ * If you've got some block of code that uses `unit`s and `bind`s, and you
+ * want to interpret it alternately using this monad, that monad, or another
+ * monad, you can use OCaml's module system. You'd write your code like this:
+ *)
+
+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 =
+ fun e -> f (u e) e;;
+end
+
+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 =
+ 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 =
+ List.concat(List.map f u);;
+end
+
+(*
+ * Then you can replace code that looks like this:
+ * ... reader_bind ...
+ * with code that looks like this:
+ * ... Reader_monad.bind ...
+ * and the latter can be reformulated like this:
+ * let open Reader_monad in ... bind ...
+ * or equivalently, like this:
+ * Reader_monad.(... bind ...)
+ * Then you can use literally the same `... bind ...` code when writing instead:
+ * State_monad.(... bind ...)
+ *)
+
+(* That's great, however it still requires us to repeat the
+ * `... bind ...` code every time we want to change which monad we're working
+ * with. Shouldn't there be a way to _parameterize_ the `... bind ...` code
+ * on a monad, so that we only have to write the `... bind ...` code once,
+ * but can invoke it alternately with the Reader_monad supplied as an
+ * 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
+ * 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
+ * do this in a moment.
+ *
+ * As preparation, a general observation: