在下面的例子中,我想用simp来证明一些术语 简单地输入lambda calculus typecheck。 我将每个类型检查规则添加为simp的重写规则,因此simp执行 条件重写并沿途创建逻辑示意图变量。 然而,在重写一些重写的边条件时,simp得到了 坚持重写涉及原理图变量的术语,因为它没有 实例化它们:
theory Stlc imports Main
begin
type_synonym var = string
datatype exp =
Var var
| Const nat
| Plus exp exp
| Abs var exp
| App exp exp
datatype type =
Nat |
Fun type type
type_synonym ('k, 'v) fmap = "'k ⇒ 'v option"
definition lookup :: "('k, 'v) fmap ⇒ 'k ⇒ 'v option" where
"lookup m x = m x"
definition add :: "('k, 'v) fmap ⇒ 'k ⇒ 'v ⇒ ('k, 'v) fmap" where
"add m x a = (λy. if y = x then Some a else m y)"
definition empty :: "('k, 'v) fmap" where
"empty = (λy. None)"
notation
lookup (infix "$?" 60) and
add ("_ $+ '( _ ', _ ')") and
empty ("$0")
inductive hasty :: "(var, type) fmap ⇒ exp ⇒ type ⇒ bool" where
HtVar:
"G $? x = Some t
⟹ hasty G (Var x) t" |
HtConst:
"hasty G (Const n) Nat" |
HtPlus:
"⟦ hasty G e1 Nat;
hasty G e2 Nat ⟧
⟹ hasty G (Plus e1 e2) Nat" |
HtAbs:
"hasty (G $+ (x, t1)) e1 t2
⟹ hasty G (Abs x e1) (Fun t1 t2)" |
HtApp:
"⟦ hasty G e1 (Fun t1 t2);
hasty G e2 t1 ⟧
⟹ hasty G (App e1 e2) t2"
named_theorems my_simps "simplification rules for typechecking"
declare HtVar [my_simps]
declare HtConst [my_simps]
declare HtPlus [my_simps]
declare HtAbs [my_simps]
declare HtApp [my_simps]
declare lookup_def [my_simps]
declare add_def [my_simps]
lemma "hasty $0 (Plus (Const 1) (Const 1)) Nat"
using [[simp_trace_new mode=full]]
apply(simp add: my_simps)
done
lemma "hasty $0 (Abs ''n'' (Abs ''m'' (Plus (Var ''n'') (Var ''m''))))
(Fun Nat (Fun Nat Nat))"
apply (simp add: my_simps)
done
lemma "⟦P ∧ Q ⟧ ⟹ Q"
apply (rule conjE)
apply(simp) (* note: this simp step does instantiate schematic variables *)
apply assumption
done
(* but here, it seems that simp does not instantiate schematic variables: *)
lemma eleven: "hasty $0 (App (App
(Abs ''n'' (Abs ''m'' (Plus (Var ''n'') (Var ''m''))))
(Const 7)) (Const 4)) Nat"
using [[simp_trace_new mode=full]]
apply (simp add: my_simps) (* seems to fail on unifying "?t1.3 = type.Nat" *)
简化程序跟踪的相关部分(我猜)如下:
Apply rewrite rule?
Instance of Option.option.inject: Some ?t1.3 = Some type.Nat ≡ ?t1.3 = type.Nat
Trying to rewrite: Some ?t1.3 = Some type.Nat
Successfully rewrote
Some ?t1.3 = Some type.Nat ≡ ?t1.3 = type.Nat
Step failed
In an instance of Stlc.hasty.HtVar:
(λy. if y = ''m'' then Some ?t1.1 else if y = ''n'' then Some ?t1.3 else $0 y) $? ''n'' = Some type.Nat ⟹
hasty (λy. if y = ''m'' then Some ?t1.1 else if y = ''n'' then Some ?t1.3 else $0 y) (Var ''n'') type.Nat ≡ True
Was trying to rewrite:
hasty (λy. if y = ''m'' then Some ?t1.1 else if y = ''n'' then Some ?t1.3 else $0 y) (Var ''n'') type.Nat
在失败的步骤之前,重写将在?t1.3 = type.Nat
处停止。
但是,我希望将?t1.3 = type.Nat
重写为True
,并且
?t1.3
在此过程中type.Nat
被实例化。
我怎样才能做到这一点?
答案 0 :(得分:1)
Isabelle的简化器本身从不实例化目标中的任何原理图变量。这只能通过所谓的求解器来完成。例如,解算器HOL unsafe
会尝试使用策略rule refl
和assumption
。这就是⟦P ∧ Q ⟧ ⟹ Q
的示例与simp
一起使用的原因。
为了解决像HtVar
这样的条件重写规则的假设,子目标也扮演着一个角色。子目标商确定如何解决条件。默认情况下,在HOL中,这是asm_simp_tac
,即等效于方法simp (no_asm_simp)
。该子代理商无法在假设中处理原理图的实例化。您可以通过启用其他简化程序跟踪来查看此内容:
using [[simp_trace]] supply [[simp_trace_depth_limit=10]]
apply (simp add: my_simps)
给出以下跟踪消息:
[6]Proved wrong theorem (bad subgoaler?)
hasty (λy. if y = ''m'' then Some ?t1.1 else if y = ''n'' then Some type.Nat else $0 y) (Var ''n'') type.Nat ≡ True
Should have proved:
hasty (λy. if y = ''m'' then Some ?t1.1 else if y = ''n'' then Some ?t1.3 else $0 y) (Var ''n'') type.Nat
因此,如果您想使用简化器进行此类型检查,则需要使用不同的子目标。我没有足够的专家来帮助你。您可以在Isabelle / Isar参考手册的9.3.6节中找到更多文档。
相反,我建议你编写自己的类型推断方法(例如,使用Eisbach),它应用类型推理规则并根据需要调用简化器。这避免了子目标的问题。
答案 1 :(得分:0)
对于这种可以通过重复应用推理规则来解决的证明目标,人们应该使用经典推理器(auto
)而不是重写器(simpl
)。 / p>
如果我将所有输入规则声明为安全的介绍规则:
declare HtVar [intro!]
declare HtConst [intro!]
declare HtPlus [intro!]
declare HtAbs [intro!]
declare HtApp [intro!]
然后我的大部分引理都由auto
证明,这留下了两个可以通过simp
解决的查找目标:
lemma eleven: "hasty $0 (App (App
(Abs ''n'' (Abs ''m'' (Plus (Var ''n'') (Var ''m''))))
(Const 7)) (Const 4)) Nat"
apply(auto)
apply(simp_all add: my_simps)
done
另外,给定一个经典的推理器,如auto
,可以很容易地指定在剩余的子目标上使用哪个重写器,如下所示,所以上面的证明可以压缩成一行:
apply(auto simp add: my_simps)
然而,给定simp
之类的重写器,指定在剩余子目标上使用哪种方法似乎更为复杂。