setoid_rewrite在模式匹配方案中失败

时间:2018-04-26 11:05:28

标签: pattern-matching coq substitution

Previously,我被告知如何 使用setoid_rewrite来处理 functional_extensionality 。不幸的是,我已经 发现这个好的解决方案在以下场景中不起作用。假设 我们已经定义了Monoid类:

Class Monoid (m : Type) :=
{ mzero : m
; mappend : m -> m -> m
}.
Notation "m1 * m2" := (mappend m1 m2) (at level 40, left associativity).

Class MonoidLaws m `{Monoid m} :=
{ left_unit  : forall m, mzero * m = m (* ; other laws... *) }.

如果我们添加pointwise_eq_ext 图片monoid_proof变得微不足道了:

Require Import Coq.Logic.FunctionalExtensionality.
Require Import Coq.Setoids.Setoid.
Require Import Coq.Classes.Morphisms.

Generalizable All Variables.

Instance pointwise_eq_ext {A B : Type} `(sb : subrelation B RB eq)
  : subrelation (pointwise_relation A RB) eq.
Proof.
  intros f g Hfg.
  apply functional_extensionality.
  intro x.
  apply sb.
  apply (Hfg x).
Qed.

Example monoid_proof `{ml : MonoidLaws m} :
  (fun m => mzero * m) = (fun m => m).
Proof. now setoid_rewrite left_unit. Qed.

但是,如果同一个monoid表达式作为option_fold的参数出现, 战术失败了:

Definition option_fold {A B} (some : A -> B) (none : B) (oa : option A) : B :=
  match oa with
  | Some a => some a
  | None => none
  end.

(* Expression is an argument for [option_fold] *)
Example monoid_proof' `{ml : MonoidLaws m} :
  forall om,
    option_fold (fun m => mzero * m) mzero om = option_fold (fun m => m) mzero om.
Proof. intros. now setoid_rewrite left_unit. (* error! *) Qed.

我不熟悉setoid_rewrite的细节,但似乎是。{ 模式匹配符合防止这种策略的上下文 正确执行。有没有办法教setoid_rewrite如何处理 这种情况?我一直试图提供几个subrelation 实例,但我缺乏理解整体的理论背景 图片。一般的解决方案会很棒,但我会很高兴 ad hoc 在(嵌套)参数中重写表达式的方法 调用option_fold

1 个答案:

答案 0 :(得分:1)

pointwise_eq_ext实例允许您重写这样的目标:

(fun m => mzero * m) = (fun m => m)

但是如果你在某个上下文中有你的功能,事情会破裂。要解决此问题,您需要添加以下子关系:

Instance subrel_eq_respect {A B : Type}
         `(sa : subrelation A RA eq)
         `(sb : subrelation B eq RB) :
   subrelation eq (respectful RA RB).
Proof. intros f g -> a a' Raa'. apply sb. f_equal. apply (sa _ _ Raa'). Qed.

您可能需要查看Matthieu Sozeau在this Coq Club post中的完整代码。