在Coq中通过类型类与记号作用域重载运算符:+和*是否特殊?
Coq中重载
+/*记号的特殊问题与解决 问题核心原因
是的,+和*在Coq中有特殊的预定义逻辑——它们同时是类型层面的多态构造器记号:
A + B对应sum类型(和类型),表示两个类型的不交并A * B对应product类型(积类型),表示两个类型的笛卡尔积
这些类型层面的记号属于type_scope,Coq的解析器在处理表达式时,会优先尝试匹配类型层面的构造,尤其是在没有明确类型指引的场景下。而-没有对应的类型构造器预定义,所以不会触发这种冲突。
当你写(pred1 + 2)时,Coq首先尝试将+解析为类型构造器,此时它期望左右操作数都是Type类型,但pred1是项层面的nat->Prop函数,因此会抛出"期望类型为Type"的错误。
解决方案
1. 绑定目标类型到自定义作用域
通过Bind Scope命令,将你的重载操作目标类型(这里是nat->Prop)绑定到自定义的mypred_scope,让Coq自动为该类型的项启用你定义的记号:
Bind Scope mypred_scope with (nat -> Prop).
添加这条命令后,Example ex2: (pred1 + 2) 2.即可正常解析,Coq会优先使用mypred_scope中的+记号。
2. 显式指定作用域
在使用记号时,通过%作用域名后缀强制指定解析规则:
Example ex2: (pred1 + 2)%mypred_scope 2. unfold pred_add, pred1; simpl; auto. Qed.
3. 限制记号的操作数类型(可选)
在定义记号时,通过约束操作数类型来避免解析歧义,不过这种方式灵活性较低:
Notation "x + y" := (pred_add x y) (at level 50, left associativity, x constr:(nat->Prop)) : mypred_scope.
验证示例
添加Bind Scope后的完整可运行代码:
Definition pred1 (a:nat) := a=1. (* pred1对应{1} *) Definition pred2 (a:nat) := a=1 /\ a=2. (* pred2对应{1,2} *) Class PredAdd (X Y Z: Type) := {pred_add: X->Y->Z->Prop}. Instance add_elem {A:Type}: PredAdd (A->Prop) (A) (A) := { pred_add (P:A->Prop) (a:A) (x:A) := P x /\ x=a }. Declare Scope mypred_scope. Notation "x + y" := (pred_add x y) (at level 50, left associativity): mypred_scope. Bind Scope mypred_scope with (nat -> Prop). Open Scope mypred_scope. Example ex1: (pred_add pred1 2) 1. unfold pred_add, pred1; simpl; auto. Qed. Example ex2: forall (p1 p2:nat->Prop) (x:nat), p1 = pred1 + 2 -> p2 = pred2 -> p1 x=p2 x. unfold pred_add, pred1, pred2; intros; subst; auto. Qed. Example ex3: (pred1 + 2) 2. unfold pred_add, pred1; simpl; auto. Qed.
内容的提问来源于stack exchange,提问作者Bodo
相关产品推荐
相关产品推荐

