存在的目标过早地被填满
Existential goals are filled in too soon
我有一个包含数据和公理的 Class
。我想基于 (1) 现有实例和 (2) 一些其他输入,以证明模式构建另一个实例。在创建记录的新实例之前,我想 destruct
第二个输入。
作为示例的最小 Class
从 jwiegley/category-theory 中的一个缩小:
Require Import Coq.Unicode.Utf8.
Require Import Coq.Init.Datatypes.
Require Import Coq.Classes.Morphisms.
Require Import Coq.Classes.SetoidDec.
Generalizable All Variables.
Reserved Infix "~>" (at level 90, right associativity).
Reserved Infix "∘" (at level 40, left associativity).
Record Category := {
obj : Type;
uhom := Type : Type;
hom : obj -> obj -> uhom where "a ~> b" := (hom a b);
homset :> ∀ X Y, Setoid (X ~> Y);
compose {x y z} (f: y ~> z) (g : x ~> y) : x ~> z
where "f ∘ g" := (compose f g);
compose_respects x y z :>
Proper (equiv ==> equiv ==> equiv) (@compose x y z);
}.
假设 (2) 是 bool
:
Definition newCat (C : Category) (b : bool) : Category.
Proof.
destruct b.
- eapply Build_Category.
Unshelve.
此时obj
填入Type
:
C : Category
============================
∀ x y z : Type, Proper (equiv ==> equiv ==> equiv) (?compose x y z)
subgoal 2 (ID 18) is:
∀ x y z : Type, (λ _ A : Type, A) y z → (λ _ A : Type, A) x y → (λ _ A : Type, A) x z
如果我删除 compose_respects
公理(或使用不带此类字段的其他类型的 Record
),此行为就会消失。如果我把Category
改成Class
,obj
就会被填成C
的obj
。它似乎与类型类解析有关(equiv
s 具有隐式类型类参数的事实?)。
有什么办法可以防止这些(或任何!)变量被统一填充?最佳结果类似于 eapply
+Unshelve
,其中根本不生成任何存在项,我可以按顺序将记录的字段作为子目标填写。
看起来 simple notypeclasses refine {| obj := _ |}
成功了。
{| obj := _|}
是作为 shorthand 用于 Build_Category _ _ _ _ _
的记录语法。
simple notypeclasses refine
都是一种策略。它是 notypeclasses refine
的一个变体,它不搁置目标并且不执行任何减少。
- 遗憾的是,与
unshelve
不同,没有通用的 notypeclasses
组合器。只有 notypeclasses refine
和 simple notypeclasses refine
.
对于调试,您可以使用(未记录的)Set Typeclasses Debug
。这表明 eapply Build_Category
确实解析了一些类型类,而 refine {| obj := _|}
更糟。
顺便说一句,我认为 Class Category
没有任何类型级参数是没有意义的 - 为什么你会想要自动推断任何类别?
我有一个包含数据和公理的 Class
。我想基于 (1) 现有实例和 (2) 一些其他输入,以证明模式构建另一个实例。在创建记录的新实例之前,我想 destruct
第二个输入。
作为示例的最小 Class
从 jwiegley/category-theory 中的一个缩小:
Require Import Coq.Unicode.Utf8.
Require Import Coq.Init.Datatypes.
Require Import Coq.Classes.Morphisms.
Require Import Coq.Classes.SetoidDec.
Generalizable All Variables.
Reserved Infix "~>" (at level 90, right associativity).
Reserved Infix "∘" (at level 40, left associativity).
Record Category := {
obj : Type;
uhom := Type : Type;
hom : obj -> obj -> uhom where "a ~> b" := (hom a b);
homset :> ∀ X Y, Setoid (X ~> Y);
compose {x y z} (f: y ~> z) (g : x ~> y) : x ~> z
where "f ∘ g" := (compose f g);
compose_respects x y z :>
Proper (equiv ==> equiv ==> equiv) (@compose x y z);
}.
假设 (2) 是 bool
:
Definition newCat (C : Category) (b : bool) : Category.
Proof.
destruct b.
- eapply Build_Category.
Unshelve.
此时obj
填入Type
:
C : Category
============================
∀ x y z : Type, Proper (equiv ==> equiv ==> equiv) (?compose x y z)
subgoal 2 (ID 18) is:
∀ x y z : Type, (λ _ A : Type, A) y z → (λ _ A : Type, A) x y → (λ _ A : Type, A) x z
如果我删除 compose_respects
公理(或使用不带此类字段的其他类型的 Record
),此行为就会消失。如果我把Category
改成Class
,obj
就会被填成C
的obj
。它似乎与类型类解析有关(equiv
s 具有隐式类型类参数的事实?)。
有什么办法可以防止这些(或任何!)变量被统一填充?最佳结果类似于 eapply
+Unshelve
,其中根本不生成任何存在项,我可以按顺序将记录的字段作为子目标填写。
看起来 simple notypeclasses refine {| obj := _ |}
成功了。
{| obj := _|}
是作为 shorthand 用于Build_Category _ _ _ _ _
的记录语法。simple notypeclasses refine
都是一种策略。它是notypeclasses refine
的一个变体,它不搁置目标并且不执行任何减少。- 遗憾的是,与
unshelve
不同,没有通用的notypeclasses
组合器。只有notypeclasses refine
和simple notypeclasses refine
.
对于调试,您可以使用(未记录的)Set Typeclasses Debug
。这表明 eapply Build_Category
确实解析了一些类型类,而 refine {| obj := _|}
更糟。
顺便说一句,我认为 Class Category
没有任何类型级参数是没有意义的 - 为什么你会想要自动推断任何类别?