Ранее , мне сказали, как
используйте setoid_rewrite
для работы с functions_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.
Однако, если то же самое моноидное выражение появляется в качестве аргумента для 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
.