考虑这个简单的发展。我有两个简单的数据类型:
Inductive A :=
| A1
| A2.
Inductive B :=
| B1 : A -> B
| B2.
现在我介绍一个关系概念,并定义数据类型A
和B
的排序,表示为归纳数据类型:
Definition relation (X : Type) := X -> X -> Prop.
Reserved Notation "a1 '<=A' a2" (at level 70).
Inductive AOrd : relation A :=
| A1_Ord : A1 <=A A1
| A2_Ord : A2 <=A A2
| A1_A2 : A1 <=A A2
where "a1 '<=A' a2" := (AOrd a1 a2).
Reserved Notation "b1 '<=B' b2" (at level 70).
Inductive BOrd : relation B :=
| B1_Ord : forall a1 a2,
a1 <=A a2 -> B1 a1 <=B B1 a2
| B2_Ord :
B2 <=B B2
| B1_B2 : forall a,
B1 a <=B B2
where "b1 '<=B' b2" := (BOrd b1 b2).
最后,我介绍了反身性的概念,并证明我的两种关系都是反身的:
Definition reflexive {X : Type} (R : relation X) :=
forall a : X, R a a.
Hint Constructors AOrd BOrd.
Theorem AOrd_reflexive : reflexive AOrd.
Proof.
intro a. induction a; auto.
Qed.
Hint Resolve AOrd_reflexive.
Theorem BOrd_reflexive : reflexive BOrd.
Proof.
intro b. induction b; auto.
Qed.
这两个证明都以auto
策略完成,第一个证据至关重要地依赖于Hint Constructors
,另外第二个证明被Hint Resolve AOrd_reflexive
添加到提示数据库。
上面代码的一个丑陋之处是对A
和B
数据类型的排序关系有一个单独的表示法。我希望能够在任何地方统一使用<=
。 This answer提供了解决问题的方法:使用类型类。所以我介绍了一个用于排序的类型类,并重新定义了我的排序关系以使用这个新的表示法:
Class OrderR (T : Type) := orderR : relation T.
Notation "x '<=' y" := (orderR x y) (at level 70).
Inductive AOrd : OrderR A :=
| A1_Ord : A1 <= A1
| A2_Ord : A2 <= A2
| A1_A2 : A1 <= A2.
Inductive BOrd `{OrderR A} : OrderR B :=
| B1_Ord : forall a1 a2,
a1 <= a2 -> B1 a1 <= B1 a2
| B2_Ord :
B2 <= B2
| B1_B2 : forall a,
B1 a <= B2.
Hint Constructors AOrd BOrd.
但现在证明自动化打破了!例如:
Theorem AOrd_reflexive : reflexive AOrd.
Proof.
intro a. induction a.
给我一个目标:
2 subgoals, subgoal 1 (ID 32)
─────────────────────────────────────────────────────
AOrd A1 A1
尽管auto
构造函数在提示数据库中,但AOrd
不再解决。我可以用constructor
来解决目标:
Theorem AOrd_reflexive : reflexive AOrd.
Proof.
intro a. induction a; constructor.
Qed.
第二次证明会出现更多问题。做完之后:
Theorem BOrd_reflexive `{OrderR A} : reflexive BOrd.
Proof.
intro b. induction b. constructor.
我留下了目标:
2 subgoals, subgoal 1 (ID 40)
H : OrderR A
a : A
─────────────────────────────────────────────────────
a <= a
再一次,auto
不再解决这个目标。即使apply AOrd_reflexive
也不起作用。
我的问题是:是否可以通过依赖类型类来保持统一的符号并保持证明自动化的好处?或者是否有针对各种数据类型的统一表示法的不同解决方案。
答案 0 :(得分:1)
不涉及类型类的解决方案是利用Coq的范围机制。
Inductive A :=
| A1
| A2.
Inductive B :=
| B1 : A -> B
| B2.
Definition relation (X : Type) := X -> X -> Prop.
Reserved Notation "a1 '<=' a2" (at level 70).
Inductive AOrd : relation A :=
| A1_Ord : A1 <= A1
| A2_Ord : A2 <= A2
| A1_A2 : A1 <= A2
where "a1 '<=' a2" := (AOrd a1 a2) : a_scope.
Delimit Scope a_scope with a.
Inductive BOrd : relation B :=
| B1_Ord : forall a1 a2,
(a1 <= a2)%a -> B1 a1 <= B1 a2
| B2_Ord :
B2 <= B2
| B1_B2 : forall a,
B1 a <= B2
where "b1 '<=' b2" := (BOrd b1 b2) : b_scope.
Delimit Scope b_scope with b.
Definition reflexive {X : Type} (R : relation X) :=
forall a : X, R a a.
Hint Constructors AOrd BOrd.
Theorem AOrd_reflexive : reflexive AOrd.
Proof.
intro a. induction a; auto.
Qed.
Hint Resolve AOrd_reflexive.
Theorem BOrd_reflexive : reflexive BOrd.
Proof.
intro b. induction b; auto.
Qed.
答案 1 :(得分:0)
问题是您的提示设置为触发,例如
SELECT * as data, topic() as topic FROM 'your topic'
,而不是@orderR _ AOrd A1 A2
。因此,自动化永远不会看到它正在寻找的模式,并且永远不会触发提示。这有两个解决方案:
(1)您可以在将构造函数添加到提示数据库时调整构造函数的类型,以便在需要时触发它们:
AOrd A1 A2
(2)您可以定义转换类型的“折叠”引理,并将其添加到数据库中:
Hint Resolve (A1_Ord : AOrd _ _) (A2_Ord : AOrd _ _) (A1_A2 : AOrd _ _).
Hint Resolve (@B1_Ord : forall H a1 a2, _ -> BOrd _ _)
(@B2_Ord : forall H, BOrd _ _)
(@B1_B2 : forall H a, BOrd _ _).