Sml 我如何在Isabelle的ML级别轻松编写简单的战术?
在Isabelle理论文件中,我可以编写简单的单行策略,如以下内容:Sml 我如何在Isabelle的ML级别轻松编写简单的战术?,sml,isabelle,Sml,Isabelle,在Isabelle理论文件中,我可以编写简单的单行策略,如以下内容: apply (clarsimp simp: split_def split: prod.splits) 然而,我发现,当我开始编写ML代码来自动校对,生成ML策略对象时,这些一行代码变得相当冗长: clarsimp_tac (Context.proof_map ( Simplifier.map_ss (fold Splitter.add_split @{thms prod.splits}) #> Sim
apply (clarsimp simp: split_def split: prod.splits)
然而,我发现,当我开始编写ML代码来自动校对,生成ML策略对象时,这些一行代码变得相当冗长:
clarsimp_tac (Context.proof_map (
Simplifier.map_ss (fold Splitter.add_split @{thms prod.splits})
#> Simplifier.map_ss (fn ss => ss addsimps [@{thm split_def}]))
@{context}) 1
在Isabelle/ML级别,有没有更简单的方法来编写简单的单行策略
例如,像反引号:@{tractic“clarsimp-simp:split_def split:prod.splits”}
生成类型为context->tractic
的函数将是一个理想的解决方案。我看到了各种可能性,这取决于应用程序的上下文。请注意,一般来说,在非常古老的时代,用于自动校对的单个ML代码曾经是常见的地方,但今天它相对较少。例如,比较小规模(始于1997年)和大规模(始于2007年,一直持续到最近)的定制战术数量
嵌套ML反旋转,如@{tractic}
原则上是可行的,但您会很快遇到进一步的问题,例如如果您的定理参数再次是Isar或ML源,会发生什么情况
与其在ML中仿效战术构建块,更基本的方法是在Isar中引用您的证明过程,为其提供如下常规方法语法:
ML {*
(*foo_tac -- the payload of what you want to do,
note the dependency on ctxt: Proof.context*)
fun foo_tac ctxt =
let
val my_ctxt =
ctxt |> Simplifier.map_simpset
(fold Splitter.add_split @{thms prod.splits} #>
Simplifier.add_simp @{thm split_def})
in ALLGOALS (clarsimp_tac my_ctxt) end
*}
method_setup foo = {*
(*concrete syntax like "clarsimp", "auto" etc.*)
Method.sections Clasimp.clasimp_modifiers >>
(*Isar method boilerplate*)
(fn _ => fn ctxt => SIMPLE_METHOD (CHANGED (foo_tac ctxt)))
*}
@{context simp add: ...}
在这里,我首先在Isabelle/ML中定义了一个传统的foo\u tac
定义,然后用通常的Isar方法将其包装起来作为证明方法。后者意味着您拥有像SIMPLE\u METHOD
这样的包装器,负责将“链接事实”推到您的目标状态,并且更改了,以确保Isar方法取得进展(比如simp
或auto
)
foo_tac
示例假定您对上下文(或其simpset)的修改根据硬连线分割规则是恒定的。如果您想在那里有更多的参数,可以将其包含在具体的方法语法中。请注意,Method.sections
在这方面已经相当成熟了。手册的“定义证明方法”一节中给出了更基本的参数解析器。您还应该通过搜索method\u setup
(在Isabelle/Isar中)或method.setup
(在Isabelle/ML中)的源代码来查看现有示例
如果您仍然希望执行ML AntiVotations而不是具体的方法语法,可以尝试使用@{context}
的一种变体,该变体允许使用如下修饰符:
ML {*
(*foo_tac -- the payload of what you want to do,
note the dependency on ctxt: Proof.context*)
fun foo_tac ctxt =
let
val my_ctxt =
ctxt |> Simplifier.map_simpset
(fold Splitter.add_split @{thms prod.splits} #>
Simplifier.add_simp @{thm split_def})
in ALLGOALS (clarsimp_tac my_ctxt) end
*}
method_setup foo = {*
(*concrete syntax like "clarsimp", "auto" etc.*)
Method.sections Clasimp.clasimp_modifiers >>
(*Isar method boilerplate*)
(fn _ => fn ctxt => SIMPLE_METHOD (CHANGED (foo_tac ctxt)))
*}
@{context simp add: ...}
这有点投机,是当场发明的,结果可能是一种不好的做法。正如我所说的,虽然ML是Isabelle框架的一个组成部分,但近年来Isabelle中的细粒度策略编程有点过时了。如果您对更多的应用程序上下文提出更具体的问题,我们可以重新考虑反旋转方法。方法
类似乎提供了足够的接口,通过案例策略
提取策略,如下所示:
(*
* Generate an ML tactic object of the given Isar string.
*
* For example,
*
* mk_tac "auto simp: field_simps intro!: ext" @{context}
*
* will generate the corresponding "tactic" object.
*)
fun mk_tac str ctxt =
let
val parsed_str = Outer_Syntax.scan Position.start str
|> filter Token.is_proper
|> Args.name
val meth = Method.method (Proof_Context.theory_of ctxt)
(Args.src (parsed_str, Position.start)) ctxt
in
Method.apply (K meth) ctxt [] #> Seq.map snd
end
setup {*
tactic_antiquotation_setup
*}
lemma "(a :: nat) * (b + 1) = (a * b) + a"
by (tactic {* @{tactic "metis Suc_eq_plus1 mult_Suc_right nat_add_commute"} @{context} *})
或者作为反报价:
(*
* Setup an antiquotation of the form:
*
* @{tactic "auto simp: foo intro!: bar"}
*
* which returns an object of type "context -> tactic".
*
* While this doesn't provide any benefits over a direct call to "mk_tac" just
* yet, in the future it may generate code to avoid parsing the tactic at
* run-time.
*)
val tactic_antiquotation_setup =
let
val parse_string =
((Args.context -- Scan.lift Args.name) >> snd)
#>> ML_Syntax.print_string
#>> (fn s => "mk_tac " ^ s)
#>> ML_Syntax.atomic
in
ML_Antiquote.inline @{binding "tactic"} parse_string
end
并在理论文件中设置,如下所示:
(*
* Generate an ML tactic object of the given Isar string.
*
* For example,
*
* mk_tac "auto simp: field_simps intro!: ext" @{context}
*
* will generate the corresponding "tactic" object.
*)
fun mk_tac str ctxt =
let
val parsed_str = Outer_Syntax.scan Position.start str
|> filter Token.is_proper
|> Args.name
val meth = Method.method (Proof_Context.theory_of ctxt)
(Args.src (parsed_str, Position.start)) ctxt
in
Method.apply (K meth) ctxt [] #> Seq.map snd
end
setup {*
tactic_antiquotation_setup
*}
lemma "(a :: nat) * (b + 1) = (a * b) + a"
by (tactic {* @{tactic "metis Suc_eq_plus1 mult_Suc_right nat_add_commute"} @{context} *})
然后可按如下方式使用:
(*
* Generate an ML tactic object of the given Isar string.
*
* For example,
*
* mk_tac "auto simp: field_simps intro!: ext" @{context}
*
* will generate the corresponding "tactic" object.
*)
fun mk_tac str ctxt =
let
val parsed_str = Outer_Syntax.scan Position.start str
|> filter Token.is_proper
|> Args.name
val meth = Method.method (Proof_Context.theory_of ctxt)
(Args.src (parsed_str, Position.start)) ctxt
in
Method.apply (K meth) ctxt [] #> Seq.map snd
end
setup {*
tactic_antiquotation_setup
*}
lemma "(a :: nat) * (b + 1) = (a * b) + a"
by (tactic {* @{tactic "metis Suc_eq_plus1 mult_Suc_right nat_add_commute"} @{context} *})
根据需要。除了其他答案之外,我认为值得一提的是,在Isabelle 2015中,有一种新的高级策略/证明方法构造语言(类似于Coq中的Ltac),其目的是更易于理解和维护。我并不热衷于使用反报价(如何从ML变量中添加参数是一个很好的观点),但我只是在寻找一种方便的方法来实例化现成的Isabelle策略(例如clarsimp
,auto
,等等)从ML代码内部。上下文是项目,它需要根据用户C代码自动生成许多证明。使用我在问题中使用的Isabelle ML接口编写/原型化此类自动证明方法可能会变得非常乏味。上面的foo_tac
和method
示例就是这样的意思clarsimp的一个“方便的实例化”,auto。您没有内联大型策略ML表达式,而是混合了辅助ML策略和Isar方法语法。您还可以以Isabelle源代码中的src/HOL/Auth为例,了解许多特定的ML策略和Isar方法(这是1990年ies中伊莎贝尔的经典战术应用程序的更新版本).src/HOL/Auth
似乎在手工编写理论文件中精心设计方法来帮助解决定理。在我的上下文中,我正在解决基于输入C文件动态创建的定理——底部没有证明脚本,而是处理由Goal.init
生成的thm
对象,而h需要一个策略来处理。在开发这种策略时,我通常只想使用“内置”Isabelle战术,但没有为每一次这样的使用生成一个相当于foo_tac
正文的冗长。你可能想研究try0
的代码。好吧,它做了一个与你提出的反引号类似的把戏。@LarsNoschinski:try0
最初看起来很有希望,但不幸的是,它在使用中起了作用ng证明状态(状态
)对象,在需要策略的情况下仍然无法使用。一种可能的方法是将部分验证的thm
注入新的证明状态对象,对其应用方法,然后提取结果;不幸的是,似乎也没有明显的机制来执行此操作。有几个问题答案和评论散布在他们身上,这让人有点难以理解。最好在isabelle users
开始一个简单的旧邮件列表讨论。