错误消息" setoid重写失败了什么:未定义的EVARS"意思?

时间:2016-11-16 04:52:37

标签: typeclass coq

我最近看到这种错误很不错:

Error:
Tactic failure: setoid rewrite failed: Unable to satisfy the following constraints:
UNDEFINED EVARS:
 ?X1700==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 |- relation M] (internal placeholder) {?r}
 ?X1701==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 (do_subrelation:=do_subrelation)
           |- Proper
                (equiv ==>
                 ?X1700@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                         __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                         __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                         __:=H0}) (sm c)] (internal placeholder) {?p}
 ?X1705==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 |- relation M] (internal placeholder) {?r0}
 ?X1706==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 |- relation M] (internal placeholder) {?r1}
 ?X1707==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 (do_subrelation:=do_subrelation)
           |- Proper
                (?X1700@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                         __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                         __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                         __:=H0} ==>
                 ?X1706@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                         __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                         __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                         __:=H0} ==>
                 ?X1705@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                         __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                         __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                         __:=H0}) sg_op] (internal placeholder) {?p0}
 ?X1708==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0
           |- ProperProxy
                ?X1706@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                        __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                        __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                        __:=H0} (- sm c mon_unit)] (internal placeholder) {?p1}
 ?X1710==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 |- relation M] (internal placeholder) {?r2}
 ?X1711==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0 (do_subrelation:=do_subrelation)
           |- Proper
                (?X1705@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                         __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                         __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                         __:=H0} ==>
                 ?X1710@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                         __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                         __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                         __:=H0} ==> flip impl) equiv] (internal placeholder) {?p2}
 ?X1712==[R M Re Rplus Rmult Rzero Rone Rnegate Me Mop Munit Mnegate sm H c
           intermediate H0
           |- ProperProxy
                ?X1710@{__:=R; __:=M; __:=Re; __:=Rplus; __:=Rmult; __:=Rzero;
                        __:=Rone; __:=Rnegate; __:=Me; __:=Mop; __:=Munit;
                        __:=Mnegate; __:=sm; __:=H; __:=c; __:=intermediate;
                        __:=H0} mon_unit] (internal placeholder) {?p3}
.

试图告诉我这是什么错误?作为参考,我最近在以下引理的工作中看到了这一点:

From MathClasses.interfaces Require Import
  abstract_algebra vectorspace canonical_names.
From MathClasses.theory Require Import groups.
Lemma mult_munit `{Module R M} : forall c : R, sm c mon_unit = mon_unit.
  intros.
  rewrite <- right_identity.
  assert (intermediate : mon_unit = sm c mon_unit & - sm c mon_unit).
  {
    rewrite right_inverse; reflexivity.
  }
  rewrite intermediate at 2.
  rewrite associativity.
  rewrite <- distribute_l.
  assert (forall x y : M, x = y -> x & sm c mon_unit = y & sm c mon_unit).
  {
    intros.
    rewrite H0.
    reflexivity.
  }
  rewrite right_identity.

我在使用数学类库进行校对时经常会看到这一点。

2 个答案:

答案 0 :(得分:3)

错误消息给我们提示: |- Proper (equiv ==> ...

重写失败,因为scalar_mult函数(其表示法为·)缺少一个非常重要的属性:它 not ProperProper函数是一个尊重等价的函数 - 记住Math-Classes库中的所有内容都定义为等价,甚至=equiv的符号,而不是{{3} }。 更正式地说,如果对于任何等效的fxx',在Math-Classes用语中),(一元)函数x = x' 正确xx'的图片也相同:f x = f x'

Proper不是“独立”变量时,我们需要此x属性才能将x'重写为x,但f适用于它。

修复错误的一种方法是在Module类型类的定义中添加一个附加字段:

sm_proper   :> Proper ((=) ==> (=) ==> (=)) (·)

上面说(·)是一个二元函数,它尊重两个参数的等价性。

喜欢这个

Class Module (R M : Type)
  {Re Rplus Rmult Rzero Rone Rnegate}
  {Me Mop Munit Mnegate}
  {sm : ScalarMult R M}
:=
  { lm_ring     :>> @Ring R Re Rplus Rmult Rzero Rone Rnegate
  ; lm_group    :>> @AbGroup M Me Mop Munit Mnegate
  ; lm_distr_l  :> LeftHeteroDistribute (·) (&) (&)
  ; lm_distr_r  :> RightHeteroDistribute (·) (+) (&)
  ; lm_assoc    :> HeteroAssociative (·) (·) (·) (.*.)
  ; lm_identity :> LeftIdentity (·) 1
  ; sm_proper   :> Proper ((=) ==> (=) ==> (=)) (·)       (* new! *)
  }.

E.g。 SemiGroup &有一个类似的字段:

Class SemiGroup {Aop: SgOp A} : Prop :=
  { sg_setoid :> Setoid A
  ; sg_ass :> Associative (&)
  ; sg_op_proper :> Proper ((=) ==> (=) ==> (=)) (&) }.

在修改之后,一切都应该有效:

Lemma mult_munit `{Module R M} :
  forall c : R, c · mon_unit = mon_unit.
Proof.
  intro c.
  rewrite <- right_identity.
  assert (intermediate : mon_unit = c · mon_unit & - (c · mon_unit)) by
    now rewrite right_inverse.
  rewrite intermediate at 2.
  rewrite associativity.
  rewrite <- distribute_l.
  rewrite right_identity.
  apply right_inverse.
Qed.

我必须补充说还有另一种方法可以证明引理,但是Coq不知道怎么找不到LeftCancellation类型的实例而没有轻推(显然这个定律适用于每个组,而MathClasses.theory.groups是进口):

  intro c.
  enough ((c · mon_unit) & (c · mon_unit) = c · mon_unit & mon_unit).
  apply (left_cancellation (&)) in H0.
  assumption.
  Print Instances LeftCancellation.   (* ! *)
  apply LeftCancellation_instance_0.  (* this is ugly, but Coq doesn't use this instance, defined in MathClasses.theory.groups *)
  rewrite <- distribute_l.
  now rewrite !right_identity.

以下是完整的开发项目:

From MathClasses.interfaces
Require Import abstract_algebra orders.
From MathClasses.theory
Require Import groups.

(** Scalar multiplication function class *)
Class ScalarMult K V := scalar_mult: K → V → V.
Instance: Params (@scalar_mult) 3.

Infix "·" := scalar_mult (at level 50) : mc_scope.
Notation "(·)" := scalar_mult (only parsing) : mc_scope.
Notation "( x ·)" := (scalar_mult x) (only parsing) : mc_scope.
Notation "(· x )" := (λ y, y · x) (only parsing) : mc_scope.

(** The inproduct function class *)
Class Inproduct K V := inprod : V → V → K.
Instance: Params (@inprod) 3.

Notation "⟨ u , v ⟩" := (inprod u v) (at level 51) : mc_scope.
Notation "⟨ u , ⟩" := (λ v, ⟨u,v⟩) (at level 50, only parsing) : mc_scope.
Notation "⟨ , v ⟩" := (λ u, ⟨u,v⟩) (at level 50, only parsing) : mc_scope.
Notation "x ⊥ y" := (⟨x,y⟩ = 0) (at level 70) : mc_scope.

(** The norm function class *)
Class Norm K V := norm : V → K.
Instance: Params (@norm) 2.

Notation "∥ L ∥" := (norm L) (at level 50) : mc_scope.
Notation "∥·∥" := norm (only parsing) : mc_scope.

(** Let [M] be an R-Module. *)
Class Module (R M : Type)
  {Re Rplus Rmult Rzero Rone Rnegate}
  {Me Mop Munit Mnegate}
  {sm : ScalarMult R M}
:=
  { lm_ring     :>> @Ring R Re Rplus Rmult Rzero Rone Rnegate
  ; lm_group    :>> @AbGroup M Me Mop Munit Mnegate
  ; lm_distr_l  :> LeftHeteroDistribute (·) (&) (&)
  ; lm_distr_r  :> RightHeteroDistribute (·) (+) (&)
  ; lm_assoc    :> HeteroAssociative (·) (·) (·) (.*.)
  ; lm_identity :> LeftIdentity (·) 1
  ; sm_proper   :> Proper ((=) ==> (=) ==> (=)) (·)
  }.

Lemma mult_munit `{Module R M} :
  forall c : R, c · mon_unit = mon_unit.
Proof.
  intro c.
  rewrite <- right_identity.
  assert (intermediate : mon_unit = c · mon_unit & - (c · mon_unit)) by
    now rewrite right_inverse.
  rewrite intermediate at 2.
  rewrite associativity.
  rewrite <- distribute_l.
  rewrite right_identity.
  apply right_inverse.

  (* alternative proof, which doesn't quite work *)
  Restart.
  intro c.
  enough ((c · mon_unit) & (c · mon_unit) = c · mon_unit & mon_unit).
  apply (left_cancellation (&)) in H0.
  assumption.
  Print Instances LeftCancellation.
  apply LeftCancellation_instance_0.
  rewrite <- distribute_l.
  now rewrite !right_identity.
Qed.

答案 1 :(得分:1)

事实证明,这确实是一个奇怪的怪癖:答案在于我使用的Proper实例仅明确引用了sm,而没有使用点符号({{1} })。当我将其更改为Anton上面使用的符号时,它可以正常工作。我会立即向数学课提出拉动请求。

编辑:这个github问题提供了一个很好的解释:https://github.com/c-corn/corn/issues/35