具有继承(:>;)的结构如何在Coq中工作?

具有继承(:>;)的结构如何在Coq中工作?,coq,coercion,Coq,Coercion,我很难理解示例中(18.9)的机制(以及Coq中的强制) 在一篇关于MathClass的文章中,有一个例子是半环和交换幺半群之间具有继承(:>)的结构: Class SemiRing A {e: Equiv} {plus: RingPlus A} {mult: RingMult A} {zero: RingZero A} {one: RingOne A}: Prop := { semiring_mult_monoid:> CommutativeMonoid A (op:=mult

我很难理解示例中(18.9)的机制(以及Coq中的强制)

在一篇关于MathClass的文章中,有一个例子是
半环
交换幺半群
之间具有继承(:>)的结构:

Class SemiRing A {e: Equiv} {plus: RingPlus A} {mult: RingMult A}
  {zero: RingZero A} {one: RingOne A}: Prop :=
{
   semiring_mult_monoid:> CommutativeMonoid A (op:=mult)(unit:=one)
 ; semiring_plus_monoid:> CommutativeMonoid A (op:=plus)(unit:=zero)
 ; semiring_distr:> Distribute mult plus
 ; semiring_left_absorb:> LeftAbsorb mult zero 
}.
我知道在数学上,半环中的乘法和加法运算(
半环{mult,plus}{m
)都是一个
交换幺半群
。另外,类
半环
交换幺半群
是类似于连词
/\
的谓词函数

从上面链接的手册中

如果ident_i:>term_i,那么ident_i将自动声明为强制 从ident到term_i的类

但在上面的例子中,我看不出这在计算上是如何工作的。在顺序方面,我们是先证明某事物
A
半环,还是先证明
交换幺半群A


在我们证明了
A
的这两个属性之一之后,我们还需要证明另一个吗?如果没有,Coq如何使用上述声明自动推断出这一点?

您可以这样做,也就是说,任何一种方法都可以。让我们为自然数构建一个
半环
类型类的实例。第一个变量可以在MathClasses库()中找到。注意:我已经通过安装了MathClasses的最新版本,所以有些名称有点不同

Require Import Coq.Arith.Arith.
Require Import MathClasses.interfaces.abstract_algebra.

Instance nat_equiv: Equiv nat := eq.
Instance nat_plus: Plus nat := Peano.plus.
Instance nat_0: Zero nat := 0%nat.
Instance nat_1: One nat := 1%nat.
Instance nat_mult: Mult nat := Peano.mult.

Instance: SemiRing nat.
Proof.
  repeat (split; try apply _); repeat intro.
         now apply plus_assoc.
        now apply plus_0_r.
       now apply plus_comm.
      now apply mult_assoc.
     now apply mult_1_l.
    now apply mult_1_r.
   now apply mult_comm.
  now apply mult_plus_distr_l.
Qed.
我们可以在这里看到,我们已经证明了
半环
s所需要的所有性质。我们没有为
交换幺半群
幺半群
,等等构建中间实例——一直到
集合集
。 由于强制机制,我们可以使用
半环nat
作为任何“前置”类型类的实例:

Goal @CommutativeMonoid nat _ plus 0. Proof. apply nat_semiring. Qed.
Goal @Monoid nat _ mult 1. Proof. apply nat_semiring. Qed.
Goal Setoid nat. Proof. apply nat_semiring. Qed.
但如果我们要求Coq打印
Monoid
typeclass(
print instances Monoid.
)的实例,那么我们将找不到隐式构建的这两个实例

上述方法可以称为自上而下的方法:我们构建一个最具表现力的typeclass实例,然后我们可以将其作为一个更抽象的实体来使用


另一种方法是使用自下而上的方法:我们从表达能力最低的typeclass开始,然后逐步将实例构建到表达能力最强的typeclass

(* ... boilerplate skipped ... *)
Ltac deduce_fields := split; try exact _; try easy.

Instance: Equivalence nat_equiv.
  deduce_fields. Qed.
Instance nat_setoid: Setoid nat.
  unfold Setoid. deduce_fields. Qed.
Instance nat_semigroup_plus: @SemiGroup nat _ plus.
  deduce_fields. exact plus_assoc. Qed.
Instance nat_semigroup_mult: @SemiGroup nat _ mult.
  deduce_fields. exact mult_assoc. Qed.
Instance nat_monoid_plus: @Monoid nat _ plus 0.
  deduce_fields. exact plus_0_r. Qed.
Instance nat_monoid_mult: @Monoid nat _ mult 1.
  deduce_fields. exact mult_1_l. exact mult_1_r. Qed.
Instance nat_comm_monoid_plus: @CommutativeMonoid nat _ plus 0.
  deduce_fields. exact plus_comm. Qed.
Instance nat_comm_monoid_mult: @CommutativeMonoid nat _ mult 1.
  deduce_fields. exact mult_comm. Qed.
Instance nat_semiring: SemiRing nat.
  deduce_fields. exact mult_plus_distr_l. Qed.
如果我们现在

Print Instances Monoid.
我们得到

(* ... *)
nat_monoid_plus : Monoid nat
nat_monoid_mult : Monoid nat
(* ... *)
因为我们已经显式地构建(并命名)了实例。一个简单的例子:

Goal @Monoid nat _ plus 0.
  exact nat_monoid_plus.    (* apply nat_semiring works too *)
Qed.

阅读本声明的另一种方式是:

Class SemiRing A {e: Equiv} {plus: RingPlus A} {mult: RingMult A}
  {zero: RingZero A} {one: RingOne A}: Prop :=
{
   semiring_mult_monoid : CommutativeMonoid A (op:=mult)(unit:=one)
 ; semiring_plus_monoid : CommutativeMonoid A (op:=plus)(unit:=zero)
 ; semiring_distr       : Distribute mult plus
 ; semiring_left_absorb : LeftAbsorb mult zero 
}.
加上相应的系数:

Coercion SemiRing A ...   >-> CommutativeMonoid A ...
Coercion SemiRing A _ m p >-> Distribute m p
等等