UniAna.infra.NeList
non-empty lists
- this module includes the definition and basic facts about non-empty lists
Require Import Lia.
Require Import Coq.Program.Equality.
Import Decidable.
Require Import Coq.Classes.Morphisms Relation_Definitions.
Require Export ListExtra.
Require Export DecTac.
Definition of non-empty lists, basic functionality and notations
Inductive ne_list (A : Type) : Type :=
| ne_single : A -> ne_list A
| ne_cons : A -> ne_list A -> ne_list A.
Arguments ne_single {_} _.
Arguments ne_cons {_} _ _.
Infix ":<:" := ne_cons (at level 70,right associativity).
Fixpoint ne_conc (A : Type) (l l' : ne_list A) : ne_list A :=
match l with
| ne_single a => a :<: l'
| ne_cons a l => a :<: ne_conc l l'
end.
Infix ":+:" := ne_conc (at level 50).
Definition ne_rcons (A : Type) l a : ne_list A := l :+: ne_single a.
Infix ":>:" := ne_rcons (at level 50).
Section NeList.
Variables (A : Type).
Fixpoint ne_front (l : ne_list A) : A
:= match l with
| ne_single a => a
| ne_cons a _ => a
end.
Fixpoint ne_back (l : ne_list A) : A
:= match l with
| ne_single a => a
| ne_cons _ l => ne_back l
end.
Fixpoint ne_to_list (l : ne_list A) : list A
:= match l with
| ne_single a => a :: nil
| a :<: l => a :: ne_to_list l
end.
End NeList.
Coercion ne_to_list : ne_list >-> list.
Fixpoint ne_tl (A : Type) (l : ne_list A) : list A
:= match l with
| ne_single _ => nil
| _ :<: l => l
end.
Ltac congruence' ::=
lazymatch goal with
| [ H : ?l ++ (?a :: ?l') = nil |- _ ] => destruct l; cbn in H; congruence
| [ H : (?l ++ ?l') :: ?a :: ?l'' = nil |- _ ] => destruct l; cbn in H; congruence
| [ H : ?l :r: ?a = nil |- _ ] => eapply rcons_not_nil in H; contradiction
| [ H : ne_to_list ?l = nil |- _ ] => destruct l; cbn in H; congruence
| [ H : nil = ?l ++ (?a :: ?l') |- _ ] => destruct l; cbn in H; congruence
| [ H : nil = (?l ++ ?l') :: ?a :: ?l'' |- _ ] => destruct l; cbn in H; congruence
| [ H : nil = ?l :r: ?a |- _ ] => symmetry in H; eapply rcons_not_nil in H; contradiction
| [ H : nil = ne_to_list ?l |- _ ] => destruct l; cbn in H; congruence
end.
Fixpoint nlcons (A : Type) (a : A) l :=
match l with
| nil => ne_single a
| b :: l => a :<: (nlcons b l)
end.
Infix ":<" := nlcons (at level 50).
Definition nl_conc (A : Type) (l : ne_list A) (ll : list A) : ne_list A :=
match ll with
| nil => l
| a :: ll => l :+: (a :< ll)
end.
Infix ":+" := nl_conc (at level 50).
Fixpoint nl_rcons (A : Type) l (a : A) : ne_list A :=
match l with
| nil => ne_single a
| b :: l => (b :<: (nl_rcons l a))
end.
Infix ">:" := nl_rcons (at level 50).
Section NeList.
Variables (A B : Type).
Lemma nlcons_to_list (a : A) l :
a :: l = nlcons a l.
Proof.
revert a. induction l; cbn; eauto. rewrite IHl. reflexivity.
Qed.
Lemma nlconc_to_list (l : ne_list A) (l' : list A)
: l ++ l' = l :+ l'.
Proof.
destruct l';cbn.
- eauto using app_nil_end.
- induction l;cbn;[rewrite <-nlcons_to_list|];eauto.
rewrite IHl. reflexivity.
Qed.
Lemma nlcons_front (a : A) l :
ne_front (nlcons a l) = a.
Proof.
induction l; cbn; eauto.
Qed.
Lemma nlcons_necons l :
forall (a : A), (a :<: l) = nlcons a l.
Proof.
induction l; cbn; eauto. rewrite IHl. reflexivity.
Qed.
Lemma nlconc_neconc (l : ne_list A) l' :
(l :+: l') = l :+ l'.
Proof.
intros. destruct l';cbn;eauto. rewrite nlcons_necons. reflexivity.
Qed.
Fixpoint ne_map (f : A -> B) (l : ne_list A) : ne_list B :=
match l with
| ne_single a => ne_single (f a)
| a :<: l => (f a) :<: ne_map f l
end.
Lemma ne_map_nlcons (f : A -> B) (a : A) l :
ne_map f (nlcons a l) = nlcons (f a) (map f l).
Proof.
revert a. induction l;intros b;cbn;firstorder.
f_equal. eauto.
Qed.
Lemma nl_rcons_back (a : A) l :
ne_back (l >: a) = a.
Proof.
induction l; cbn; eauto.
Qed.
Lemma ne_rcons_back (a : A) l :
ne_back (l :>: a) = a.
Proof.
induction l; cbn; eauto.
Qed.
Lemma to_list_ne_map (f : A -> B) (l : ne_list A) :
map f l = ne_map f l.
Proof.
intros. induction l;cbn;eauto. rewrite IHl. reflexivity.
Qed.
Lemma ne_back_map (f : A -> B) l :
ne_back (ne_map f l) = f (ne_back l).
Proof.
induction l; firstorder.
Qed.
Lemma ne_to_list_inj (l l' : ne_list A) :
ne_to_list l = ne_to_list l' -> l = l'.
Proof.
Set Printing Coercions.
revert l'. induction l; induction l'; intros Heq; inversion Heq; cbn in *.
- reflexivity.
- exfalso. destruct l'; cbn in H1; congruence.
- exfalso. destruct l; cbn in H1; congruence.
- apply IHl in H1. subst l. econstructor.
Unset Printing Coercions.
Qed.
Lemma ne_map_in (f:A->B) a (l:ne_list A) :
In a l -> In (f a) (ne_map f l).
Proof.
intro Hin. induction l;cbn.
- inversion Hin;[subst;tauto|contradiction].
- cbn in Hin. destruct Hin;subst.
+ left. reflexivity.
+ right. eauto.
Qed.
Lemma ne_map_nl_rcons (l : list A) a (f : A -> B)
: ne_map f (l >: a) = (map f l) >: (f a).
Proof.
induction l;cbn;eauto. rewrite IHl. reflexivity.
Qed.
Lemma rcons_nl_rcons l (a:A) :
l :r: a = nl_rcons l a.
Proof.
induction l; eauto. rewrite cons_rcons_assoc. rewrite IHl. cbn. reflexivity.
Qed.
Lemma ne_to_list_not_nil (l : ne_list A) :
nil <> l.
Proof.
intro N. induction l; cbn in *; congruence.
Qed.
Lemma nercons_nlrcons l (a : A)
: l :>: a = l >: a.
Proof.
induction l;cbn;eauto. rewrite <-IHl. destruct l;eauto.
Qed.
Lemma rcons_necons l (a : A)
: (ne_to_list l) :r: a = l :>: a.
Proof.
induction l;cbn;eauto. rewrite IHl. reflexivity.
Qed.
Lemma ne_list_nlcons (l : ne_list A)
: exists a l', l = a :< l'.
Proof.
destruct l as [a | a l'];exists a;[exists nil|exists l'];cbn;[|rewrite <-nlcons_necons];reflexivity.
Qed.
Lemma ne_list_nlrcons: forall (A : Type) (l : ne_list A), exists (a : A) (l' : list A), l = l' >: a.
Proof.
induction l.
- exists a, nil. eauto.
- destructH. rewrite IHl. exists a0, (a :: l'). cbn. reflexivity.
Qed.
Lemma neconc_app (l l' : ne_list A)
: l ++ l' = l :+: l'.
Proof.
induction l;cbn;eauto.
rewrite IHl. reflexivity.
Qed.
Lemma nl_cons_lr_shift (a b : A) (l : list A)
: (a :<: (l >: b)) = ((a :< l) :>: b).
Proof.
revert a.
induction l; intros; cbn ; eauto.
fold ((ne_rcons (a :< l) b)). rewrite IHl. reflexivity.
Qed.
Lemma in_nlcons (l : list A) (a b : A)
: a ∈ (b :< l) <-> a = b \/ a ∈ l.
Proof.
split; intro Q.
- revert dependent b. induction l; cbn in *;intros b Q;[firstorder|].
destruct Q;[firstorder|].
right. specialize (IHl a0 H). firstorder.
- revert dependent b. induction l; cbn in *;intros b Q;[firstorder|].
destruct Q;[firstorder|].
right. eapply IHl. firstorder.
Qed.
Lemma in_ne_conc (l l' : ne_list A)
: forall a, a ∈ (l :+: l') <-> a ∈ l \/ a ∈ l'.
Proof.
split; revert a; induction l;intros b Q; cbn in *; firstorder 0.
Qed.
Lemma in_nl_conc (l : ne_list A) l' (a : A)
: a ∈ (l :+ l') <-> a ∈ l \/ a ∈ l'.
Proof.
split;revert a;induction l'; intros b Q; cbn in *; [firstorder| |firstorder|].
- eapply in_ne_conc in Q. repeat destruct Q; eauto. eapply in_nlcons in H. destruct H;eauto.
- eapply in_ne_conc. repeat destruct Q; eauto. right. eapply in_nlcons. firstorder.
Qed.
End NeList.
Lemma nin_tl_iff (A : Type) `{EqDec A eq} (a : A) (l : ne_list A)
: a ∉ tl (rev l) -> a ∉ l \/ a = ne_back l.
Proof.
intros.
decide' (a == ne_back l);eauto.
left. contradict H0. induction l;cbn in *;eauto.
- destruct H0;eauto. congruence.
- fold ((rev l) :r: a0).
rewrite tl_rcons;[eapply In_rcons;eauto|destruct l;cbn;eauto;erewrite app_length;cbn;lia].
destruct H0.
+ subst. eauto.
+ right. eapply IHl;eauto.
Qed.
Lemma find_some' (A : Type) (f : A -> bool) (l : list A) (x : A)
(Hl : x ∈ l)
(Hf : f x = true)
: exists y, Some y = find f l.
Proof.
induction l;cbn;[contradiction|].
destruct Hl;subst.
- rewrite Hf. eauto.
- destruct (f a);eauto.
Qed.