存在的目标过早地被填满

Existential goals are filled in too soon

我有一个包含数据和公理的 Class。我想基于 (1) 现有实例和 (2) 一些其他输入,以证明模式构建另一个实例。在创建记录的新实例之前,我想 destruct 第二个输入。

作为示例的最小 Classjwiegley/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改成Classobj就会被填成Cobj。它似乎与类型类解析有关(equivs 具有隐式类型类参数的事实?)。

有什么办法可以防止这些(或任何!)变量被统一填充?最佳结果类似于 eapply+Unshelve,其中根本不生成任何存在项,我可以按顺序将记录的字段作为子目标填写。

看起来 simple notypeclasses refine {| obj := _ |} 成功了。

  • {| obj := _|} 是作为 shorthand 用于 Build_Category _ _ _ _ _ 的记录语法。
  • simple notypeclasses refine 都是一种策略。它是 notypeclasses refine 的一个变体,它不搁置目标并且不执行任何减少。
  • 遗憾的是,与 unshelve 不同,没有通用的 notypeclasses 组合器。只有 notypeclasses refinesimple notypeclasses refine.

对于调试,您可以使用(未​​记录的)Set Typeclasses Debug。这表明 eapply Build_Category 确实解析了一些类型类,而 refine {| obj := _|} 更糟。

顺便说一句,我认为 Class Category 没有任何类型级参数是没有意义的 - 为什么你会想要自动推断任何类别?