具有继承(:>;)的结构如何在Coq中工作?
我很难理解示例中(18.9)的机制(以及Coq中的强制) 在一篇关于MathClass的文章中,有一个例子是具有继承(:>;)的结构如何在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
半环
和交换幺半群
之间具有继承(:>)的结构:
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
等等