在Coq表示法

时间:2018-01-23 04:06:31

标签: syntax typeclass coq notation

我正试图把我的脑袋包裹在Coq中的类型类中(我过去曾涉足过它,但我与经验丰富的用户相去甚远)。作为练习,我正在尝试编写一个小组理论库。这就是我想出来的:

Class Group {S : Type} {op : S → S → S} := {
  id : S;

  inverse : S → S;

  id_left {x} : (op id x) = x;
  id_right {x} : (op x id) = x;

  assoc {x y z} : (op (op x y) z) = (op x (op y z));

  right_inv {x} : (op x (inverse x)) = id;
}.

我特别喜欢隐含的Sop参数(假设我正确理解它们)。

为反转做一些表示很容易:

Notation "- x" := (@inverse _ _ _ x)
  (at level 35, right associativity) : group_scope.

现在,我想x * y(op x y)提供简写。使用部分时,这很简单:

Section Group.
Context {S} {op} { G : @Group S op }.

(* Reserved at top of file *)
Notation "x * y" := (op x y) : group_scope.
(* ... *)
End Group.

但是,由于这是在一个部分中声明的,因此其他地方无法访问该表示法。如果可能的话,我想在全球范围内声明符号。我遇到的问题(与inverse相反)是因为opGroup的隐式参数,它实际上并不存在于全局范围内的任何地方(所以我(@op _ _ _ x y))无法引用它。这个问题告诉我,我要么使用类型错误,要么不理解如何将符号与隐式变量集成。有人能指出我正确的方向吗?

答案(2018年1月25日)

基于Anton Trunov's response,我能够编写以下内容,其中有效:

Reserved Notation "x * y" (at level 40, left associativity).

Class alg_group_binop (S : Type) := alg_group_op : S → S → S.

Delimit Scope group_scope with group.
Infix "*" := alg_group_op: group_scope.

Open Scope group_scope.

Class Group {S : Type} {op : alg_group_binop S} : Type := {
  id : S;

  inverse : S → S;

  id_left {x} : id * x = x;
  id_right {x} : x * id = x;

  assoc {x y z} : (x * y) * z = x * (y * z);

  right_inv {x} : x * (inverse x) = id;

}.

2 个答案:

答案 0 :(得分:4)

以下是PierreCastéran和Matthieu Sozeau如何在A Gentle Introduction to Type Classes and Relations in Coq(§3.9.2)中解决这个问题:

  

来自 ibid。的解决方案在于声明用于表示二元运算符的单例类型类:

Class monoid_binop (A:Type) := monoid_op : A -> A -> A.
     

Nota :与多字段类类型不同,monoid_op不是构造函数,而是透明常量,使monoid_op f可以δβ减少为{{1} }。

     

现在可以声明中缀表示法:

f
     

我们现在可以使用Delimit Scope M_scope with M. Infix "*" := monoid_op: M_scope. Open Scope M_scope. 类型代替Monoid,使用中缀符号monoid_binop A代替A → A → A来提供x * y的新定义:

monoid_op x y

答案 1 :(得分:1)

皮埃尔·卡斯特兰(PierreCastéran)和马蒂乌·索佐(Matthiu Sozeau)可能就是这样处理它的原因。

但不会

Definition group_op {S op} {G : @Group S op} := op.
Infix "*" := group_op.

也在这里工作? (我只尝试了两个非常基本的测试用例。)

这将使您无需更改Group的定义。