是否有可能实施检查HintDb的Coq策略?如果是这样,怎么样?

时间:2017-03-10 03:25:13

标签: coq coq-tactic ltac

例如,我想要一个可以迭代给定HintDb中所有解析提示的策略,并且对于每个解析提示h,它会执行pose h.。这可能吗?如果是这样,怎么样?

1 个答案:

答案 0 :(得分:4)

在Coq中,没有(除非你使用shelve进行奇特的事情并且回溯),但在OCaml中它非常简单。例如,在菲亚特项目中,我们有这样的策略。对于Coq 8.7:

hint_db_extra_tactics.ml中:

module WITH_DB =
  struct
    open Tacticals.New
    open Names
    open Ltac_plugin

  (* [tac] : string representing identifier *)
  (* [args] : tactic arguments *)
  (* [ltac_lcall] : Build a tactic expression calling a variable let-bound to a tactic == [F] args *)
  let ltac_lcall tac args =
    Tacexpr.TacArg(Loc.tag @@ Tacexpr.TacCall(Loc.tag @@ (Misctypes.ArgVar(Loc.tag @@ Names.Id.of_string tac),args)))

  (* [ltac_letin] : Build a let tactic expression. let x := e1 in e2 *)
  let ltac_letin (x, e1) e2 =
    Tacexpr.TacLetIn(false,[(Loc.tag @@ Names.Id.of_string x),e1],e2)

  (* [ltac_apply] : Run a tactic with arguments... *)
  let ltac_apply (f: Tacinterp.Value.t) (arg:Tacinterp.Value.t) =
    let open Geninterp in
    let ist = Tacinterp.default_ist () in
    let id = Id.of_string "X" in
    let idf = Id.of_string "F" in
    let ist = { ist with Tacinterp.lfun = Id.Map.add idf f (Id.Map.add id arg ist.lfun) } in
    let arg = Tacexpr.Reference (Misctypes.ArgVar (Loc.tag id)) in
    Tacinterp.eval_tactic_ist ist
      (ltac_lcall "F" [arg])

  (* Lift a constructor to an ltac value. *)
  let to_ltac_val c = Tacinterp.Value.of_constr c

  let with_hint_db dbs tacK =
    let open Proofview.Notations in
    (* [dbs] : list of hint databases *)
    (* [tacK] : tactic to run on a hint *)
    Proofview.Goal.nf_enter begin
        fun gl ->
        let syms = ref [] in
        let _ =
          List.iter (fun l ->
                     (* Fetch the searchtable from the database*)
                     let db = Hints.searchtable_map l in
                     (* iterate over the hint database, pulling the hint *)
                     (* list out for each. *)
                     Hints.Hint_db.iter (fun _ _ hintlist ->
                                         syms := hintlist::!syms) db) dbs in
        (* Now iterate over the list of list of hints, *)
        List.fold_left
          (fun tac hints ->
           List.fold_left
             (fun tac (hint : Hints.full_hint) ->
              let hint1 = hint.Hints.code in
              Hints.run_hint hint1
                       (fun hint2 ->
                              (* match the type of the hint to pull out the lemma *)
                              match hint2 with
                                Hints.Give_exact ((lem, _, _) , _)
                              | Hints.Res_pf ((lem, _, _) , _)
                              | Hints.ERes_pf ((lem, _, _) , _) ->
                                 let this_tac = ltac_apply tacK (Tacinterp.Value.of_constr lem) in
                                 tclORELSE this_tac tac
                              | _ -> tac))
             tac hints)
          (tclFAIL 0 (Pp.str "No applicable tactic!")) !syms
      end

  let add_resolve_to_db lem db =
    let open Proofview.Notations in
    Proofview.Goal.nf_enter begin
        fun gl ->
        let _ = Hints.add_hints true db (Hints.HintsResolveEntry [({ Vernacexpr.hint_priority = Some 1 ; Vernacexpr.hint_pattern = None },false,true,Hints.PathAny,lem)]) in
        tclIDTAC
      end

end

hint_db_extra_plugin.ml4中:

open Hint_db_extra_tactics
open Stdarg
open Ltac_plugin
open Tacarg

DECLARE PLUGIN "hint_db_extra_plugin"

TACTIC EXTEND foreach_db
  | [ "foreach" "[" ne_preident_list(l) "]" "run" tactic(k) ]  ->
     [ WITH_DB.with_hint_db l k ]
       END

TACTIC EXTEND addto_db
  | [ "add" constr(name) "to" ne_preident_list(l) ]  ->
     [ WITH_DB.add_resolve_to_db (Hints.IsConstr (name, Univ.ContextSet.empty)) l]
       END;;

hint_db_extra_plugin.mllib中:

Hint_db_extra_tactics
Hint_db_extra_plugin

HintDbExtra.v中:

Declare ML Module "hint_db_extra_plugin".

使用它来解决问题陈述中提出的例子,我们可以添加:

_CoqProject

-R . Example
-I .
HintDbExtra.v
PoseDb.v
hint_db_extra_plugin.ml4
hint_db_extra_plugin.mllib
hint_db_extra_tactics.ml

PoseDb.v

Require Import HintDbExtra.

Ltac unique_pose v :=
  lazymatch goal with
  | [ H := v |- _ ] => fail
  | _ => pose v
  end.

Goal True.
  repeat foreach [ core ] run unique_pose.

如果你想在提示数据库中的每个提示上运行一个策略(而不是在每个提示上连续运行一个策略,直到找到一个成功的提示),你可以更改{{1}中的tclORELSE某种排序操作符(例如with_hint_db)。