diff --git a/coq/DemoEqReasoning.v b/coq/DemoEqReasoning.v new file mode 100644 index 0000000..eade91a --- /dev/null +++ b/coq/DemoEqReasoning.v @@ -0,0 +1,73 @@ +Require Import List. + +Section Demo. + +(* -------------------------------------------------------------------------- *) + +Variables A B : Type. +Variable p : B -> bool. +Variable f : A -> B. + +(* The composition of [filter] and [map] can be computed by the specialized + function [filter_map]. *) + +Fixpoint filter_map xs := + match xs with + | nil => + nil + | cons x xs => + let y := f x in + if p y then y :: filter_map xs else filter_map xs + end. + +Lemma filter_map_spec: + forall xs, + filter p (map f xs) = filter_map xs. +Proof. + induction xs as [| x xs ]; simpl. + { reflexivity. } + { rewrite IHxs. reflexivity. } +Qed. + +(* -------------------------------------------------------------------------- *) + +(* [filter] and [map] commute in a certain sense. *) + +Variable q : A -> bool. + +Lemma filter_map_commute: + (forall x, p (f x) = q x) -> + forall xs, + filter p (map f xs) = map f (filter q xs). +Proof. + intros h. + induction xs as [| x xs ]; simpl; intros. + (* Case: [nil]. *) + { reflexivity. } + (* Case: [x :: xs]. *) + { rewrite h. + rewrite IHxs. + (* Case analysis: [q x] is either true or false. + In either case, the result is immediate. *) + destruct (q x); reflexivity. } +Qed. + +(* In a slightly stronger version of the lemma, the equality [p (f x) = q x] + needs to be proved only under the hypothesis that [x] is an element of the + list [xs]. *) + +Lemma filter_map_commute_stronger: + forall xs, + (forall x, In x xs -> p (f x) = q x) -> + filter p (map f xs) = map f (filter q xs). +Proof. + induction xs as [| x xs ]; simpl; intro h. + { reflexivity. } + { (* The proof is the same as above, except the two rewriting steps have + side conditions, which are immediately proved by [eauto]. *) + rewrite h by eauto. + rewrite IHxs by eauto. + destruct (q x); reflexivity. } +Qed. + +End Demo.