coq-club AT inria.fr
Subject: The Coq mailing list
List archive
- From: Tom Prince <tom.prince AT ualberta.net>
- To: Coq Club <coq-club AT inria.fr>
- Subject: [Coq-Club] Re: Ltac automation.
- Date: Sat, 12 Feb 2011 23:00:16 -0500
(* I managed to come up with a couple of solutions to my automation
problem *)
(******** SETUP ***)
Inductive Term :=
| Var: nat → Term
| Op: Term → Term → Term.
Fixpoint eval_term {A: Type} (op: A → A → A) (var: nat → A) (t: Term) :=
match t with
| Var n => var n
| Op x y => op (eval_term op var x) (eval_term op var y)
end.
Inductive Equal := Eq: Term → Term → Equal.
Fixpoint eval_eq {A: Type} (op: A → A → A) (var: nat → A) (e: Equal) :=
let (x, y) := e in (eval_term op var x) = (eval_term op var y).
Inductive Laws : Equal -> Prop :=
| law_1 : Laws (Eq (Var 0) (Op (Var 0) (Var 1)))
| law_2 : Laws (Eq (Op (Var 0) (Var 0)) (Op (Var 1) (Var 0))).
Axiom (A: Type).
Axiom (op: A→A→A).
Definition laws_true_type := λ {E} (_: Laws E), ∀ x y, eval_eq op (fun n =>
match n with | 0 => x | _ => y end) E.
Axiom (laws_true: ∀ {E} (laws: Laws E), laws_true_type laws).
Record rec (A: Type) (op: A→A→A) := { m1 : ∀ x y, x = (op x y) ; m2: ∀ x y,
(op x x) = (op y x) }.
(******** END ***)
(* Here is the manual solution to the problem *)
Goal rec A op.
constructor; [apply (laws_true law_1) | apply (laws_true law_2)].
Defined.
(* Now, I know each of the goals can be solved by applying laws_true to
a constructor, so I wanted to figure out how to refer to constuctors by
number, so I could iterate over them: *)
Goal rec A op.
constructor.
let n:= fresh in (evar (n:Equal); assert (Laws n) as P; subst n; [
constructor 1 | apply (laws_true P)]).
let n:= fresh in (evar (n:Equal); assert (Laws n) as P; subst n; [
constructor 2 | apply (laws_true P)]).
Defined.
(* Then I ran into problems trying to iterate.
- the constructor tactic only takes numbers, not ltac variables bound
to numbers
(http://www.lix.polytechnique.fr/coq/bugs/show_bug.cgi?id=2496)
- you can do arithmetic with and matching with numbers represented as
coq terms, but you can't then pass those numbers to tactics
expecting numbers like constructor or do.
I created patches for both these issues; although the second should
probably do more sanity checking to insure the term is actually meant
to be a number.
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml index 917a98c..fb454d9 100644 --- a/tactics/tacinterp.ml +++ b/tactics/tacinterp.ml @@ -1046,8 +1046,41 @@ let interp_hint_base ist s = try try_interp_ltac_var coerce_to_hint_base ist None (dloc,id_of_string s) with Not_found -> s +(**** BEGIN: copied from plugins/syntax_nat_syntax.ml and plugins/micromega/coq_micromega.ml ******) +exception Non_closed_number + +let get_left_construct term = + match Term.kind_of_term term with + | Term.Construct(_,i) -> (i,[| |]) + | Term.App(l,rst) -> + (match Term.kind_of_term l with + | Term.Construct(_,i) -> + (i,rst) + | _ -> raise Non_closed_number) + | _ -> raise Non_closed_number +let rec parse_nat term = + let (i,c) = get_left_construct term in + match i with + | 1 -> 0 + | 2 -> 1 + (parse_nat (c.(0))) + | i -> raise Non_closed_number + +let uninterp_nat p = + try + Some (parse_nat p) + with + Non_closed_number -> None +(**** END: copied from plugins/syntax_nat_syntax.ml and plugins/micromega/coq_micromega.ml ******) + let coerce_to_int = function | VInteger n -> n + | VConstr ([], c) -> + try + match uninterp_nat c with + | Some n -> n + | None -> raise (CannotCoerceTo "an integer") + with + Non_closed_number -> raise (CannotCoerceTo "an integer") | v -> raise (CannotCoerceTo "an integer") let interp_int ist locid =
Thus, the following code works.
*)
Goal rec A op.
Tactic Notation "do_with_nat" constr(n) tactic(T) := let rec LOOP n := match
n with S ?n' => T n || LOOP n' end in LOOP n.
constructor; do_with_nat 2 fun k => let n:= fresh "n" in (evar (n:Equal);
assert (Laws n) as P; subst n); [ constructor k | apply (laws_true P) ].
Defined.
(* But, it would be nice avoid the contusions required above. So I
pieced together two tactics in ML, that do exactly what I need.
Caml1999M012 7plugins/intro/intro.ml4 Ph S = <砠"Pp7plugins/intro/intro.ml4CkkCkr@$Pcoq
Dss
Ds|@&GenargE}}E} H@)ExtraargsF I IF I W@)Mod_subst!G X X"G X f@%Names)H g g*H g q@'Tacexpr1I r r2I r ~@)Glob_term9J :J @'TacticsAK BK @$UtilIL JL @#EvdQM RM @(EqualityYN ZN @&CompataO bO @'RefineriP jP @'TacmachqQ rQ @@"ic|T}T@
@!cTT@@#envU
U#@&Global#envU&U0@
"()@@U0U2@@U&U2@%sigmaU7U<@#Evd%emptyU?UH@@,Constrintern-interp_constrVLNVLh@)%sigmaVLiVLn@2#envVLoVLr@;!cVLsVLt@@VLNVLt@UUt@@TTt@@TTt@@"tyXvzXv|@{@!cXv}Xv~@&Typing'type_of
Xv
Xv@p&Global#envXvXv@}|@@!Xv"Xv@@$Xv%Xv@#Evd%empty/Xv0Xv@!c8Xv9Xv@@;Xv<Xv@@>Xv}?Xv@@AXvvBXv@@)ltac_callL[M[@@#tacV[W[@@$argsb[c[@$list/glob_tactic_arg@n[o[@@q[r[@t[u[@&TacArg'TacCall)dummy_loc\\@&ArgArg)dummy_loc\\&@$Lazy%force\(\2@#tac\3\6@@\(\6@@\\7@@\\7@$args\8\<@@\\=@@\\=@@\\>@@[[>@@[[>@@[[>@@*ltac_lcall_ei_es@_@#tac_et_ew@i@$args_ex_e|@&TacArg'TacCall)dummy_loc``@&ArgVar)dummy_loc``@,id_of_string``@#tac&`'`@@)`*`@@,`-`@@/`0`@$args7`8`@@:`;`@@=`>`@@@`A`@@C_exD_e@@F_etG_e@@I_eeJ_e@@*ltac_letinTbUb@@!xabbb@"e1hbib@@kblb@@"e2ubvb@(TacLetIn%false@@cc@"::)dummy_loccc@,id_of_stringc c
@!xc
c@@c c@@cc@"e1cc@@cc@"[]@@cc@@cc@@cc@"e2cc@@cc@@cc@@bb@@bb@@bb@@*ltac_applyee'@r@!fe)e*@0glob_tactic_expr@e+e;@e(e<@@$argse>eB@$list/glob_tactic_arg@eCeR@@eC
eW@"e=#eX@)Tacinterp+eval_tactic-f[].f[r@*ltac_letin8gsx9gs@!FDgsEgs@&Tacexp!fQgsRgs@@TgsUgs@@WgsXgs@*ltac_lcallbgscgs@Ơ!Fkgslgs@Ϡ$argstgsugs@@wgsxgs@@zgsx{gs@@}f[]~f[@@e=e@@e(e@@ee@@+ltac_recordii@@$fldsii@&TacFun$Some,id_of_stringjj@$projjj@@jj@@jj@
@@jj@@jj@@jj@*ltac_lcalljj@B$projjj@K$fldsjj@@jj@@jj@@jj@@ii@@i i@@$carg
mm
@@!cm
m@*TacDynamic)dummy_loc#m$m"@)Pretyping)constr_in/m#0m6@!c8m79m8@@;m#<m8@@>m?m9@@AmBm9@@Dm
Em9@@GmHm9@,DeclarationsOqMMPqM^@$TermWr__Xr_h@@*map_constrbtjnctjx@@!cltjymtjz@@#tacvtj{wtj~@@"gltjtj@@$minduu@%redcluu@@uu@;pf_reduce_to_quantified_induu@"gluu@
!cuu@@uu@@@'nconstrvv@%Array&lengthvv@.#sndvv@;&Global0lookup_inductivevv@H$mindvv@@vv@@vv@.mind_consnamesvv
@@vv
@@@$consww@$List#mapww&@t@!iw,w-@+mkConstruct%w1&w<@<ith_constructor_of_inductive0w>1wZ@$mind9w[:w_@!iBw`Cwa@@Ew>Fwa@@Hw1Iwb@@Kw(Lwb@(intervalVxdmWxdu@A^xdv_xdw@ 'nconstrgxdxhxd@@jxdmkxd@@mwnw@@$List#mapxyyy@ܠ@!cyy@*ltac_applyyy@#tacyy@$cargyy@
!cyy@@yy@@@yy@@yy@@yy@@yy@@yy@+$consyy@@yy@ww@vv@uu@@tjtj@@tj{tj@@tjytj@@tjjtj@@/try_with_constr{{@w@!c{{@@#tac{{@@"gl{{@(tclFIRST||@~*map_constr%|&|@!c.|/|@#tac7|8|@"gl@|A|@@C|D|@"glL|M|@@O|P|@@R{S{@@U{V{@@X{Y{@@[{\{@@/for_each_constrf~ g~ @@!cp~ q~ @@#tacz~ {~ @@"gl~ ~ @+tclTHENLIST"-@*map_constr/9@!c:;@#tac<?@"gl@B@@/B@"glEG@@!G@@~ ~ G@@~ ~ G@@~ ~ G@@~ ~ G@@1h_try_with_constr AII AI@]@!c Bg Bg@g@#tac Bg Bg@'Refiner8abstract_extended_tactic AII AI@\/try_with_constr
@@ @@Af"::&Genarg&in_gen Bg Bg@{&Genarg*wit_constr"