[MLton-commit] r6386
Vesa Karvonen
vesak at mlton.org
Tue Feb 5 07:42:57 PST 2008
Some more comments.
----------------------------------------------------------------------
U mltonlib/trunk/com/ssh/generic/unstable/example/canonize.sml
----------------------------------------------------------------------
Modified: mltonlib/trunk/com/ssh/generic/unstable/example/canonize.sml
===================================================================
--- mltonlib/trunk/com/ssh/generic/unstable/example/canonize.sml 2008-02-05 10:34:57 UTC (rev 6385)
+++ mltonlib/trunk/com/ssh/generic/unstable/example/canonize.sml 2008-02-05 15:42:56 UTC (rev 6386)
@@ -6,19 +6,17 @@
open Generic
-(**
- * This is a simple example of using the {Reduce} and {Transform}
+(* This is a simple example of using the {Reduce} and {Transform}
* generics. The program reads a term given as an argument and shows the
* canonized version of the term. Canonization renames bindings so that
- * alpha equivalent terms have the same representation.
- *)
+ * alpha equivalent terms have the same representation. *)
(* The {Lambda} module defines the representation of the terms of our toy
* language. Identifiers are just strings. Crucial to the use of the
* {Reduce} and {Transform} generics is that the terms of the language are
* defined as a fixed point of a functor, {f}. This allows the {Reduce}
- * and {Transform} generics to operate on all the subterms of a given
- * term.
+ * and {Transform} generics to operate on all the immediate subterms of a
+ * given term.
*
* The commented ellipsis in the definition of the term functor suggests
* that one could add further variants to the term. Doing so means that
@@ -87,7 +85,7 @@
fun difference (xs, ys) = List.filter (not o List.contains ys) xs
end
-(* {free term} returns a set of the free variables in the given term. *)
+(* {free term} returns a set of the free variables in the given {term}: *)
local
open Set
val refs = fn REF id => singleton id | _ => empty
@@ -99,20 +97,36 @@
reduce empty union free term),
decs term)
end
+(* To understand how the {free} function works, note that the {refs} and
+ * {decs} functions return just the immediate variable references and
+ * declarations in the given term. They don't process the term
+ * recursively. To process the entire term recursively, the {free}
+ * function uses {reduce} to process the immediate subterms of the term
+ * using itself, {free}, as the reducer.
+ *
+ * The {reduce} function, obtained here via the type representation, saves
+ * us from pattern matching over all the variants. Only the variable
+ * reference and declaration variants need to be treated explicitly. *)
(* {renameFree it to term} renames free variables named {it} to {to} in
- * the given {term}. *)
+ * the given {term}: *)
fun renameFree it to (IN term) = let
- val recurse = transform (renameFree it to)
+ fun recurse () = transform (renameFree it to) term
in
IN (case term
- of FUN (v, _) => if v = it then term else recurse term
+ of FUN (v, _) => if v = it then term else recurse ()
| REF v => if v = it then REF to else term
- | _ => recurse term)
+ | _ => recurse ())
end
+(* Except for using {transform} rather than {reduce}, the {renameFree}
+ * function uses essentially the same pattern as the {free} function. The
+ * variable reference and declaration variants are first examined
+ * explicitly. Then, if necessary, {renameFree} uses {transform} to
+ * process the immediate subterms of the term using itself as the
+ * transformer. *)
(* {countFuns term} returns the number of {FUN} variants in the given
- * {term}. *)
+ * {term}: *)
local
val countHere = fn FUN _ => 1 | _ => 0
in
@@ -121,9 +135,7 @@
end
(* {canonize term} gives canonic names to all bound variables in the
- * given term. Here the canonic name of a bound variable is the number of
- * {FUN} subterms in the body of the {FUN} term that introduces the
- * variable. *)
+ * given {term}: *)
local
val canonizeHere =
fn FUN (v, t) => let
@@ -137,7 +149,10 @@
fun canonize (IN term) =
IN (canonizeHere (transform canonize term))
end
+(* Here the canonic name of a bound variable is the number of {FUN}
+ * subterms in the body of the {FUN} term that introduces the variable. *)
+(* Here is an example term: *)
val exampleTerm =
IN (APP (IN (FUN ("x",
IN (APP (IN (REF "x"), IN (REF "x"))))),
@@ -165,8 +180,7 @@
end
(* The main program just reads a given term and shows the canonized
- * version or shows an example term.
- *)
+ * version or shows an example term: *)
val () =
case CommandLine.arguments ()
of [e] => say "And here is the canonized term:" (canonize (read t e))
@@ -179,4 +193,5 @@
*
* Another unrelated exercise would be to design a concrete syntax for
* the language and write a parser and pretty-printer for the concrete
- * syntax. *)
+ * syntax. This example just lazily uses the generic {read} and {show}
+ * functions obtained via the type representation. *)
More information about the MLton-commit
mailing list