(*
We would like to investigate the idea of directly using OCaml to produce Coq-readable language.
The idea would be to make heavy use of the advanced and higher-level features of OCaml to get around
the conceptual problems one encounters in dealing with complicated mathematical structures directly
in Coq.
The present file is only the first part of this attempt. In it we set up a type of expressions,
do beta-reduction for these (with a parameter limiting the depth of the recurrence so it doesn't
loop), construct a type_of function, and a printing function which outputs a string which is supposed
to be readable by Coq (and where the meaning in Coq is supposed to be what it looks like from the
constructor names in the expression type). These last may only hold if we apply it to expressions
that are "well-written"; just as in a natural language it is possible to have grammatical phrases
which don't have any meaning, here too it is possible to have expressions which don't have
any real meaning in Coq. However we claim that one can write all meaningful expressions in
(the small subset of Coq which is implemented) by the printing function. The printing suggestion
PrintDB yields a de Bruijn-style numbering of variables, whereas PrintAs allows one to specify the
string to be used.
At the end we begin to investigate how to generate expressions in a convivial manner. One remark
here is that it seems important to use the functional type unit -> expression rather than just expression,
in order to easily handle the problem of replacing variables in an expression (construction of lambda-terms).
Carlos Simpson
September 3 2002
*)
type suggestion = PrintDB | PrintAs of string;;
type expression =
Type
| New of string * expression
| App of expression * expression
| Prod of suggestion * expression * (expression -> expression)
| Lambda of suggestion * expression * (expression -> expression);;
let rec beta_reduce e i =
if i < 0 then e else
match e with
Type -> Type
| New(n,t) -> New(n, beta_reduce t (i-1))
| App(f,z) -> let g = (beta_reduce f (i-1)) in begin match g with
Lambda(h,t,u) -> beta_reduce (u z) (i-1)
| _ -> App(g, beta_reduce z (i-1)) end
| Prod(h,t,u) -> Prod (h,beta_reduce t (i-1), function w -> (beta_reduce (u w) (i-1)))
| Lambda(h,t,u) -> Lambda(h,beta_reduce t (i-1), function w -> (beta_reduce (u w) (i-1)));;
let namex i = "x"^(string_of_int i);;
let varx i t = New (namex i, t);;
let forall a b c = "("^a^": "^b^")"^c;;
let mapsto a b c = "["^a^": "^b^"]"^c;;
let rec ccprint e i =
match e with
Type -> "Type"
| New(n,t) -> n
| App(f,z) -> "("^(ccprint f i) ^" " ^(ccprint z i) ^")"
| Prod(h,t,u) -> begin match h with
PrintDB -> forall (namex i) (ccprint t (i + 1)) (ccprint (u (varx i t)) (i+1))
| PrintAs n -> forall n (ccprint t i) (ccprint (u (New(n, t))) i) end
| Lambda(h,t,u) -> begin match h with
PrintDB -> mapsto (namex i) (ccprint t (i + 1)) (ccprint (u (varx i t)) (i+1))
| PrintAs n -> mapsto n (ccprint t i) (ccprint (u (New(n, t))) i) end;;
exception Function_not_in_product_type;;
let rec type_of e =
match e with
Type -> Type
| New(n,t) -> t
| App(f,z) -> begin match (type_of f) with
Prod(h,t,u) ->(u z)
| _ ->raise Function_not_in_product_type end
| Prod(h,t,u) -> Type
| Lambda(h,t,u) -> Prod(h,t, function x -> (type_of (u x)));;
(***** now we start trying to create expressions in a functional way ****)
type readvarflagtype = Read | DontRead | Suggest;;
let readvarflag = ref DontRead;;
let globalexp = ref Type;;
let globalsugg = ref PrintDB;;
class vari vsugg =
object (self)
val mutable currentexp = Type
method the_var () = match !readvarflag with
Read -> currentexp <- !globalexp; currentexp
| Suggest -> globalsugg := vsugg; currentexp
| DontRead -> currentexp
end;;
let newvariable nvsugg =
let x = new vari nvsugg in
x#the_var;;
let ttype = function () -> Type;;
let app f x = function () -> App (f(), x());;
let replace x e u =
function () ->
begin
readvarflag := Read;
globalexp := e;
x();
readvarflag := DontRead;
u()
end;;
let get_sugg x =
begin
readvarflag := Suggest;
x ();
readvarflag := DontRead;
!globalsugg
end;;
let lambda x t u = function () ->
Lambda (get_sugg x, t(), function e -> replace x e u ());;
let prod x t u = function () ->
Prod (get_sugg x, t(), function e -> replace x e u ());;
let fprint a = ccprint (a ()) 0;;
let ftype_of a = function () -> (type_of (a ()));;
(*** note that the following expression is not actually well-typed
but it looks pretty much like a standard coq expression ***)
let xx = newvariable (PrintAs "X");;
let aa = newvariable PrintDB;;
let test1 = lambda xx (prod aa ttype ttype) (app xx xx);;
fprint test1;; (* - : string = "[X: (x0: Type)Type](X X)" *)
let test2 = lambda xx (prod xx ttype ttype) (app xx xx);;
fprint test2;; (* - : string = "[X: (X: Type)Type](X X)" *)
let test3 = lambda aa (prod aa ttype ttype) (app aa aa);;
fprint test3;; (* - : string = "[x0: (x1: Type)Type](x0 x0)" *)
fprint (ftype_of test1);; (* - : string = "(X: (x0: Type)Type)Type" *)
(* etc *)