Chapter 8 - Lists


Require Export Base.

8.1 Constructors and Notation


(* Commented because of naming conflicts with the Base library: 
 
Inductive list (X : Type) : Type :=
| nil : list X
| cons : X -> list X -> list X.

Notation "x '::' A" := (cons x A) (at level 60).
*)


Check list.
Check nil.
Check cons.

Goal (X: Type) (x: X) (A: list X), cons x A = x :: A.
Proof. reflexivity. Qed.

Goal (X: Type) (x y: X) (A: list X), cons x (cons y A) = x :: y :: A.
Proof. reflexivity. Qed.

8.2 Recursion and Induction


(* Commented because of naming conflicts with the Base library:
Fixpoint length (X: Type) (A: list X) :=
  match A with
    | => 0
    |x :: A => S (length A)
  end.
    
Notation "| A |" := (length A) (at level 65). 

Fixpoint app (X: Type) (A B: list X) :=
  match A with
    | => B
    |x :: A => x :: (app A B)
  end.

Notation "| A ++ B |" := (app A B) (at level 70). 

Fixpoint rev (X: Type) (A: list X) :=
  match A with
    | => 
    |x :: A => rev A ++ x
  end.

Fixpoint map (X Y: Type) (f: X -> Y) (A: list X) :=
  match A with
    | => 
    |x :: A => f x :: map f A
  end.

Fixpoint list_prod (X Y: Type) (A: list X) (B: list Y) :=
  match A with
    | => 
    |a :: A => map (pair a) B ++ (list_prod A B)
  end. *)


Compute (list_prod [1;2] [5;6;7]).

Goal (X: Type) (A B: list X), |A ++ B| = |A| + |B|.
Proof.
  intros X A B. induction A as [|x A IHA].
  - reflexivity.
  - simpl. rewrite IHA. reflexivity.
Qed.

(* Exercise 8.2.2 *)

Lemma list_cycle (X : Type) (A : list X) x :
  x::A A.
Abort.

(* Exercise 8.2.3 *)

Section Ex23.
  Variable X Y: Type.
  Variable x: X.
  Variable A B C: list X.
  Variable f: X Y.

  Lemma app_nil_r:
    A ++ nil = A.
  Abort.

  Lemma app_assoc:
    A ++ (B ++ C) = (A ++ B) ++ C.
  Abort.

  Lemma rev_app_distr:
    rev (A ++ B) = rev B ++ rev A.
  Abort.

  Lemma map_app:
    map f (A ++ B) = (map f A) ++ (map f B).
  Abort.

  Lemma app_length:
  |A ++ B| = |A| + |B|.
  Abort.

  Lemma rev_length:
  |rev A| = |A|.
  Abort.

  Lemma map_length:
  |map f A| = |A|.
  Abort.

  Lemma prod_length:
  |list_prod A B| = |A| × |B|.
  Abort.

  Lemma rev_involutive:
    rev (rev A) = A.
  Abort.

  Lemma rev_unit:
    rev (A ++ [x]) = x :: rev A.
  Abort.

End Ex23.

(* Exercise 8.2.4 *)
Fixpoint revi (X: Type) (A B: list X) :=
  match A with
    |[]B
    |x :: Arevi A (x :: B)
  end.

Goal (X: Type) (A B: list X),
       revi A B = rev A ++ B.
Abort.

Goal (X: Type) (A: list X),
       rev A = revi A nil.
Abort.

(* Exercise 8.2.5 *)

(* Definition lengthi (X: Type) : list X -> nat -> nat :=

Goal forall (X: Type) (A:list X),
         length A = lengthi A. *)


8.3 Membership


(* Commented because of naming conflicts with the Base library: 
 
Fixpoint In (X: Type) (a: X) (A: list X) :=
  match A with
    | => False
    |x :: A => x = a \/ In a A
  end.

Notation "x 'el' A" := (In x A) (at level 70).
*)


(* Exercise 8.3.1 *)

Goal (A B C: list nat), ¬ (3 el []) 2 el A ++ (1 :: 2 :: B) ++ C.
Abort.

(* Exercise 8.3.2 *)

Section Ex32.
  Variable X: Type.
  Variable x y: X.
  Variable A B: list X.

  Lemma in_eq:
    x el x :: A.
  Abort.

  Lemma in_cons:
    x el A x el y :: A.
  Abort.

  Lemma in_or_app:
    x el A x el B x el A ++ B.
  Abort.

  Lemma in_nil:
    ¬ (x el []).
  Abort.

  Lemma in_sing:
    x el [y] x = y.
  Abort.

  Lemma in_cons_neq:
    x el y::A x y x el A.
  Abort.

  Lemma not_in_cons:
    ¬ x el y :: A x y ¬ x el A.
  Abort.

End Ex32.

(* Exercise 8.3.3 *)

Section Ex33.

  Lemma in_app_iff (X : Type) (A B: list X) (x :X):
    x el A ++ B x el A x el B.
  Abort.

  Lemma in_rev_iff (X: Type) (x: X) (A: list X):
    x el rev A x el A.
  Abort.

  Lemma in_map_iff (X Y: Type) (f: X Y) (x: Y) (A: list X):
    x el map f A y, f y = x y el A.
  Abort.

  Lemma in_prod_iff (X Y: Type) (A: list X) (B: list Y) (a: X) (b: Y):
    (a, b) el list_prod A B a el A b el B.
  Abort.

End Ex33.

(* Exercise 8.3.4 *)

(* Inductive con (* ... *)

Definition con_ind (* ... *)
          
Goal forall (X: Type) (A B C: list X),
      con A B C <-> A ++ B = C.
*)


8.4 Inclusion and Equivalence


(* Commented because of naming conflicts with the Base library:   
Definition incl (X: Type) (xs ys: list X) :=
  forall a, a el xs -> a el ys.

Notation "A <<= B" := (incl A B) (at level 70).


Definition equi (X: Type) (xs ys: list X) :=
  xs <<= ys /\ ys <<= xs.

Notation "A === B" := (equi A B) (at level 70).
*)


Goal A B C, A <<= B 2 :: A ++ 3 :: A <<= C ++ 3 :: 2 :: B.
Proof.
  auto 7.
Qed.

Goal X (x y : X) A B, x::A ++ [y] ++ A ++ B === A ++ [y;x] ++ A ++ B.
Proof.
  intros X x y A B. simpl. rewrite equi_swap. rewrite equi_shift at 1. reflexivity.
Qed.

Goal (A B C D : list nat), A <<= B B <<= C C <<= D A <<= D.
Proof.
  intros A B C D F G H. rewrite F. rewrite G. exact H.
Qed.

(* Exercise 8.4.2  *)

Section Ex42.
  Variable X: Type.
  Implicit Types A B C: list X.

  Lemma incl_refl A:
    A <<= A.
  Abort.

  Lemma incl_tl x A B:
    A <<= B A <<= x::B.
  Abort.

  Lemma incl_cons x A B:
    x el B A <<= B x :: A <<= B.
  Abort.

  Lemma incl_appl A B C:
    A <<= B A <<= B ++ C.
  Abort.

  Lemma incl_appr A B C:
    A <<= C A <<= B ++ C.
  Abort.

  Lemma incl_app A B C:
    A <<= C B <<= C A ++ B <<= C.
  Abort.

  Lemma incl_nil A:
    nil <<= A.
  Abort.

  Lemma incl_nil_eq A :
    A <<= nil A=nil.
  Abort.

  Lemma incl_shift x A B :
    A <<= B x::A <<= x::B.
  Abort.

  Lemma incl_lcons x A B :
    x::A <<= B x el B A <<= B.
  Abort.

  Lemma incl_sing x A y :
    x::A <<= [y] x = y A <<= [y].
  Abort.

  Lemma incl_rcons x A B :
    A <<= x::B ¬ x el A A <<= B.
  Abort.

  Lemma incl_lrcons x A B :
    x::A <<= x::B ¬ x el A A <<= B.
  Abort.

  Lemma incl_app_left A B C :
    A ++ B <<= C A <<= C B <<= C.
  Abort.

  Lemma incl_map A B Y (f: X Y):
    A <<= B map f A <<= map f B.
  Abort.

  Lemma equi_push x A :
    x el A A === x::A.
  Abort.

  Lemma equi_dup x A :
    x::A === x::x::A.
  Abort.

  Lemma equi_swap x y A:
    x::y::A === y::x::A.
  Abort.

  Lemma equi_shift x A B :
    x::A++B === A++x::B.
  Abort.

  Lemma equi_rotate x A :
    x::A === A++[x].
  Abort.

End Ex42.

(* Exercise 8.4.4 Don't be confused by the syntax of instances. The proofs just work as usual lemmas! *)
Instance incl_preorder X :
  PreOrder (@incl X).
Proof.
  constructor.
Abort.

Instance equi_Equivalence X :
  Equivalence (@equi X).
Proof.
  constructor.
Abort.

(* Exercise 8.4.4 *)

Instance incl_equi_proper X :
  Proper (@equi X ==> @equi X ==> iff) (@incl X).
Proof.
  hnf.
Abort.

Instance cons_incl_proper X x :
  Proper (@incl X ==> @incl X) (@cons X x).
Proof.
  hnf.
Abort.

Instance cons_equi_proper X x :
  Proper (@equi X ==> @equi X) (@cons X x).
Proof.
  hnf.
Abort.

(* Exercise 8.4.5 *)

(* Inductive mem (X: Type) (x : X) : list X -> Prop := (* ... *)

Goal forall (X: Type) (x: X) (A: list X), mem x A <-> x el A. *)


8.5 Disjointness


(* Commented because of naming conflicts with the Base library:   

Definition disjoint A B :=
  ~ exists x, x el A /\ x el B. 
*)


(* Exercise 8.5.1 *)

Section Disjoint.
  Variable X: Type.
  Implicit Types A B: list X.

  Lemma disjoint_forall A B :
    disjoint A B x, x el A ¬ x el B.
  Abort.

  Lemma disjoint_symm A B :
    disjoint A B disjoint B A.
  Abort.

  Lemma disjoint_incl A B B' :
    B' <<= B disjoint A B disjoint A B'.
  Abort.

  Lemma disjoint_nil B :
    disjoint nil B.
  Abort.

  Lemma disjoint_nil' A :
    disjoint A nil.
  Abort.

  Lemma disjoint_cons x A B :
    disjoint (x::A) B ¬ x el B disjoint A B.
  Abort.

  Lemma disjoint_app A B C :
    disjoint (A ++ B) C disjoint A C disjoint B C.
  Abort.

End Disjoint.

8.6 Decidability


Print list_eq_dec.
Print list_in_dec.
Print list_forall_dec.
Print list_exists_dec.

Goal X A B (p : X Prop),
  eq_dec X ( x, dec (p x)) dec (A=B x, x el A y, y el B (y el A ¬ p x)).
Proof. auto. Qed.

Instance iff_dec (X Y : Prop) :
  dec X dec Y dec (X Y).
Proof. unfold dec; tauto. Qed.

(* Exercise 8.6.1 *)

Goal X (A B : list X), eq_dec X dec (A === B).
Abort.

(* Exercise 8.6.2 *)

Goal X A B (p : X Prop),
       eq_dec X ( x, dec (p x)) dec (A=B x, x el A y, y el B (y el A ¬ p x)).
Abort.

(* Exercise 8.6.3 *)

Instance list_eq_dec X :
  eq_dec X eq_dec (list X).
Abort.

Instance list_in_dec (X : Type) (x : X) (A : list X) :
  eq_dec X dec (x el A).
Abort.

Instance list_forall_dec X A (p : X Prop) :
  ( x, dec (p x)) dec ( x, x el A p x).
Abort.

Instance list_exists_dec X A (p : X Prop) :
  ( x, dec (p x)) dec ( x, x el A p x).
Abort.

(* Exercise 8.6.4 *)
Lemma list_sigma_forall X A (p : X Prop) (p_dec : x, dec (p x)) :
  {x | x el A p x} + { x, x el A ¬ p x}.
Abort.

Lemma list_exists_DM X A (p : X Prop) :
  ( x, dec (p x))
  ¬ ( x, x el A ¬ p x) x, x el A p x.
Abort.

Lemma list_exists_not_incl X (A B : list X) :
  eq_dec X
  ¬ A <<= B x, x el A ¬ x el B.
Abort.

Lemma list_cc X (p : X Prop) A :
  ( x, dec (p x))
  ( x, x el A p x) {x | x el A p x}.
Abort.


8.7 Filtering


(* Commented because of naming conflicts with the Base library:   

Definition filter (X : Type) (p : X -> Prop) (p_dec : forall x, dec (p x)) : list X -> list X :=
  fix f A := match A with
              | nil => nil
              | x::A' => if decision (p x) then x :: f A' else f A'
             end.

Arguments filter {X} p {p_dec} A.

Definition decision (X : Prop) (D : dec X) : dec X := D.
Arguments decision X {D}.
 *)


Compute filter (fun x ⇒ 3 x 7) [1;2;3;4;5;6;7;8;9].

Lemma in_filter_iff X (p : X Prop) {p_dec : x, dec (p x)} x A :
  x el filter p A x el A p x.
Proof.
  induction A as [|y A]; simpl.
  - tauto.
  - decide (p y) as [B|B]; simpl; rewrite IHA; intuition; subst; tauto.
Qed.

(* Exercise 8.7.1 *)

Section FilterLemmas.
  Variable X : Type.
  Variable p q: X Prop.
  Context {p_dec : x, dec (p x)}.
  Context {q_dec : x, dec (q x)}.

  Goal x A,
    x el filter p A x el A p x.
  Abort.

  Lemma filter_incl A :
    filter p A <<= A.
  Abort.

  Lemma filter_mono A B :
    A <<= B filter p A <<= filter p B.
  Abort.

  Lemma filter_pq_mono A :
    ( x, x el A p x q x) filter p A <<= filter q A.
  Abort.

  Lemma filter_pq_eq A :
    ( x, x el A (p x q x)) filter p A = filter q A.
  Abort.

  Lemma filter_id A :
    ( x, x el A p x) filter p A = A.
  Abort.

  Lemma filter_app A B :
    filter p (A ++ B) = filter p A ++ filter p B.
  Abort.

  Lemma filter_fst x A :
    p x filter p (x::A) = x::filter p A.
  Abort.

  Lemma filter_fst' x A :
    ¬ p x filter p (x::A) = filter p A.
  Abort.

End FilterLemmas.


(* Exercise 8.7.2 *)

(* Fixpoint inter (X: Type) (A B: list X) : list X :=
  (* ... *)

Goal forall (X: Type) (x: X) (A B: list X),
       x el inter A B <-> x el A /\ x el B.
Abort. *)


8.8 Element Removal


(* Commented because of naming conflicts with the Base library:   

Variable X : Type.
Context {eq_X_dec : eq_dec X}.

Definition rem (A : list X) (x : X) : list X :=
 filter (fun z => z <> x) A. 
*)


(* Exercise 8.8.1 *)

Section Removal.
  Variable X : Type.
  Context {eq_X_dec : eq_dec X}.

  Lemma in_rem_iff x A y :
    x el rem A y x el A x y.
  Abort.

  Lemma rem_not_in x y A :
    x = y ¬ x el A ¬ x el rem A y.
  Abort.

  Lemma rem_incl A x :
    rem A x <<= A.
  Abort.

  Lemma rem_mono A B x :
    A <<= B rem A x <<= rem B x.
  Abort.

  Lemma rem_inclr A B x :
    A <<= B ¬ x el A A <<= rem B x.
  Abort.

  Lemma rem_cons A B x :
    A <<= B rem (x::A) x <<= B.
  Abort.

  Lemma rem_cons' A B x y :
    x el B rem A y <<= B rem (x::A) y <<= B.
  Abort.

  Lemma rem_app x A B :
    x el A B <<= A ++ rem B x.
  Abort.

  Lemma rem_app' x A B C :
    rem A x <<= C rem B x <<= C rem (A ++ B) x <<= C.
  Abort.

  Lemma rem_in x y A :
    x el rem A y x el A.
  Abort.

  Lemma rem_neq x y A :
    x y x el A x el rem A y.
  Abort.

  Lemma rem_equi x A :
    x::A === x::rem A x.
  Abort.

  Lemma rem_reorder x A :
    x el A A === x :: rem A x.
  Abort.

  Lemma rem_comm A x y :
    rem (rem A x) y = rem (rem A y) x.
  Abort.

  Lemma rem_fst x A :
    rem (x::A) x = rem A x.
  Abort.

  Lemma rem_fst' x y A :
    x y rem (x::A) y = x::rem A y.
  Abort.

  Lemma rem_id x A :
    ¬ x el A rem A x = A.
  Abort.

End Removal.

8.9 Cardinality


(* Commented because of naming conflicts with the Base library:   

  Variable X : Type.
  Context { eq_X_dec : eq_dec X }.
  Implicit Types A B : list X.

  Fixpoint card A :=
    match A with
      | nil => 0
      | x::A => if decision (x el A) then card A else 1 + card A
    end.
*)


Print card.

(* Exercise 8.9.2 *)

Section Ex92.
  Variable X : Type.
  Context { eq_X_dec : eq_dec X }.
  Implicit Types A : list X.

  Lemma card_in_rem x A :
    x el A card A = 1 + card (rem A x).
  Abort.

End Ex92.

(* Exercise 8.9.3 *)

Section Ex93.
  Variable X : Type.
  Context { eq_X_dec : eq_dec X }.
  Implicit Types A : list X.

 Lemma card_le A B :
    A <<= B card A card B.
 Abort.

End Ex93.

8.10 Duplicate-Freeness


(* Commented because of naming conflicts with the Base library:   
Inductive dupfree (X : Type) : list X -> Prop :=
| dupfreeN : dupfree nil
| dupfreeC x A : ~ x el A -> dupfree A -> dupfree (x::A).

Fixpoint undup (X: Type) (H: eq_dec X) (A : list X) : list X :=
  match A with
    | nil => nil
    | x::A' => if decision (x el A') then undup H A' else  x :: undup H A'
  end.

*)


(* Exercise 8.10.1 *)

Section Dupfree.
  Variable X: Type.
  Context {eq_X_dec : eq_dec X}.
  Implicit Type A: list X.

  Lemma dupfree_card A:
    dupfree A card A = |A|.
  Abort.

  Lemma dupfree_dec A :
    dec (dupfree A).
  Abort.

  Lemma dupfree_undup A :
    dupfree (undup A).
  Abort.

  Lemma undup_id_equi A :
    undup A === A.
  Abort.

End Dupfree.

(* Exercise 8.10.2 *)

Section Dupfree2.
  Variable X: Type.
  Context {eq_X_dec : eq_dec X}.
  Implicit Type A: list X.

  Lemma dupfree_app A B :
    disjoint A B dupfree A dupfree B dupfree (A++B).
  Abort.

  Lemma dupfree_map Y A (f : X Y) :
    ( x y, x el A y el A f x = f y x=y)
    dupfree A dupfree (map f A).
  Abort.

  Lemma dupfree_filter p (p_dec : x, dec (p x)) A :
    dupfree A dupfree (filter p A).
  Abort.

End Dupfree2.

8.11 Power Lists


(* Commented because of naming conflicts with the Base library:   

Fixpoint power (X: Type) (U : list X ) : list (list X) :=
  match U with
    | nil => nil
    | x :: U' => power U' ++ map (cons x) (power U')
  end.

Definition rep (X: Type) (H: eq_dec X) (A U : list X) : list X :=
  filter (fun x => x el A) U.
*)


(* Exercise 8.11.1 *)

Section PowerRep.
  Variable X : Type.
  Context {eq_X_dec : eq_dec X}.
  Implicit Types A U: list X.

  Lemma power_incl A U :
    A el power U A <<= U.
  Abort.

  Lemma power_nil U :
    nil el power U.
  Abort.

  Lemma rep_power A U :
    rep A U el power U.
  Abort.

  Lemma rep_incl A U :
    rep A U <<= A.
  Abort.

  Lemma rep_in x A U :
    A <<= U x el A x el rep A U.
  Abort.

  Lemma rep_equi A U :
    A <<= U rep A U === A.
  Abort.

  Lemma rep_mono A B U :
    A <<= B rep A U <<= rep B U.
  Abort.

  Lemma rep_eq A B U :
    A === B rep A U = rep B U.
  Abort.

  Lemma rep_injective A B U :
    A <<= U B <<= U rep A U = rep B U A === B.
  Abort.

  Lemma rep_idempotent A U :
    rep (rep A U) U = rep A U.
  Abort.

  Lemma dupfree_power U :
    dupfree U dupfree (power U).
  Abort.

  Lemma dupfree_in_power U A :
    A el power U dupfree U dupfree A.
  Abort.

  Lemma rep_dupfree A U :
    dupfree U A el power U rep A U = A.
  Abort.

  Lemma power_extensional A B U :
    dupfree U A el power U B el power U A === B A = B.
  Abort.

End PowerRep.