Module Utils
From Stdlib Require Import Lists.List.From Stdlib Require Import Arith.Compare_dec.
From Stdlib Require Import PeanoNat.
From Stdlib Require Import Lia.
From Stdlib Require Import Classes.RelationClasses.
Import Nat.
Import ListNotations.
Module Learn.
Inductive Learnt {P:Prop} :=
| AlreadyLearnt (H:P).
Local Ltac learn_fact H :=
let P := type of H in
lazymatch goal with
| [ Hlearnt: @Learnt P |- _ ] =>
fail 0 "already knew" P "through" Hlearnt
| _ => pose proof H; pose proof (AlreadyLearnt H)
end.
Tactic Notation "learn" constr(H) := learn_fact H.
End Learn.
Module Utils.
Import Learn.
Ltac inv H := inversion H; clear H; subst.
Ltac antisym :=
match goal with
| [ H: ?x <= ?y, F: ?y <= ?x |- _ ] =>
learn (le_antisymm _ _ H F)
end
.
Ltac splitHyp :=
match goal with
| [ H: _ /\ _ |- _ ] => destruct H
end
.
Ltac existsHyp :=
match goal with
| [ H: ex _ |- _ ] => destruct H
end
.
Fixpoint mapI'{X Y: Type} f i (l: list X) : list Y :=
match l with
| [] => []
| hd :: tl => f i hd :: mapI' f (i + 1) tl
end
.
Definition mapI {X Y: Type} (f: nat -> X -> Y) := mapI' f 0.
Lemma mapI'_values : forall (X Y: Type) (f: nat -> X -> Y) (l: list X) y i,
In y (mapI' f i l) <-> exists n x, nth_error l n = Some x /\ y = f (i + n) x.
Proof.
induction l.
- split; intros. contradiction. destruct H as [[|n] [x [H1 H2]]]; discriminate H1.
- split; intros.
+ destruct H as [H1 | H2].
* exists 0. exists a. intuition. assert (HNat: i + 0 = i). lia. rewrite HNat. auto.
* rewrite IHl in H2. destruct H2 as [n [x [H1 H2]]].
exists (1 + n). exists x. intuition. assert (HNat: i + (1 + n) = i + 1 + n). lia.
rewrite HNat. apply H2.
+ destruct H as [n [x [H1 H2]]]. destruct n.
* inversion H1. subst. left. assert (HNat: i + 0 = i). lia. rewrite HNat.
reflexivity.
* right. apply IHl. exists n. exists x. intuition. assert (HNat: i + 1 + n = i + S n). lia.
rewrite HNat. apply H2.
Qed.
- split; intros. contradiction. destruct H as [[|n] [x [H1 H2]]]; discriminate H1.
- split; intros.
+ destruct H as [H1 | H2].
* exists 0. exists a. intuition. assert (HNat: i + 0 = i). lia. rewrite HNat. auto.
* rewrite IHl in H2. destruct H2 as [n [x [H1 H2]]].
exists (1 + n). exists x. intuition. assert (HNat: i + (1 + n) = i + 1 + n). lia.
rewrite HNat. apply H2.
+ destruct H as [n [x [H1 H2]]]. destruct n.
* inversion H1. subst. left. assert (HNat: i + 0 = i). lia. rewrite HNat.
reflexivity.
* right. apply IHl. exists n. exists x. intuition. assert (HNat: i + 1 + n = i + S n). lia.
rewrite HNat. apply H2.
Qed.
Lemma mapI_values : forall (X Y: Type) (f: nat -> X -> Y) (l: list X) y,
In y (mapI f l) <-> exists n x, nth_error l n = Some x /\ y = f n x.
Proof.
Fixpoint maxList x l :=
match l with
| [] => x
| hd :: tl => max hd (maxList x tl)
end
.
Fixpoint sum (l: list nat) :=
match l with
| [] => 0
| hd :: tl => hd + sum tl
end
.
Lemma and_with_impl : forall P Q, P -> (P -> Q) -> P /\ Q.
Proof.
split; intros; auto.
Qed.
Qed.
Ltac splitAnd :=
match goal with
| [ |- _ /\ _ ] => apply and_with_impl; [idtac|intros]
end
.
Definition list_sep {T: Type} (l: list T) :=
match l with
| [] => None
| hd :: _ => Some (removelast l, last l hd)
end
.
Definition le_option_nat (x y : option nat) : Prop :=
match x, y with
| None, _ => True
| Some _, None => False
| Some a, Some b => a <= b
end.
Instance le_option_nat_Reflexive : Reflexive le_option_nat.
Proof.
intros [n|]; simpl; auto.
Qed.
Qed.
Lemma max_dec_bis: forall a b, (max a b = a /\ b <= a) \/ (max a b = b /\ a <= b).
Proof.
Ltac _useMaxDecBis :=
match goal with
| [ H: (_ = _ /\ _) \/ (_ = _ /\ _) |- _ ] =>
destruct H as [[?Heq ?H]|[?Heq ?H]]; rewrite Heq in *; clear Heq
end
.
Ltac splitMax :=
match goal with
| [ H: context[max ?x ?y] |- _ ] => learn (max_dec_bis x y); _useMaxDecBis
| [ |- context[max ?x ?y] ] => learn (max_dec_bis x y); _useMaxDecBis
end
.
Lemma nth_error_lists : forall A B (l: list A) (l': list B) n x,
nth_error l n = Some x -> length l = length l' -> exists y, nth_error l' n = Some y.
Proof.
induction l; intros.
- destruct n; discriminate H.
- destruct l'. discriminate H0. inv H0. destruct n.
+ eexists. reflexivity.
+ firstorder.
Qed.
- destruct n; discriminate H.
- destruct l'. discriminate H0. inv H0. destruct n.
+ eexists. reflexivity.
+ firstorder.
Qed.
Ltac gen_nth :=
match goal with
| [ Hlen: length ?l1 = length ?l2, Hnth: nth_error ?l1 ?n = Some _ |- _ ] =>
destruct (nth_error_lists _ _ _ _ _ _ Hnth Hlen); clear Hlen
| [ Hlen: length ?l2 = length ?l1, Hnth: nth_error ?l1 ?n = Some _ |- _ ] =>
let HnewTh := fresh in assert(HnewTh: exists y, nth_error l2 n = Some y) by
(apply (nth_error_lists _ _ _ _ _ _ Hnth); symmetry; apply Hlen);
destruct HnewTh; clear Hlen
end
.
Lemma option_eq_dec : forall (T: Type) (x y: option T),
(forall x y: T, {x = y} + {x <> y}) -> {x = y} + {x <> y}.
Proof.
intros. destruct x; destruct y; try (destruct (X t0 t1)); subst;
left + right; congruence.
Qed.
left + right; congruence.
Qed.