(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)


(* Contribution to the Coq Library   V6.3 (July 1999)                    *)

(****************************************************************************)
(*                 The Calculus of Inductive Constructions                  *)
(*                                                                          *)
(*                                Projet Coq                                *)
(*                                                                          *)
(*                     INRIA                        ENS-CNRS                *)
(*              Rocquencourt                        Lyon                    *)
(*                                                                          *)
(*                                Coq V5.10                                 *)
(*                              Nov 25th 1994                               *)
(*                                                                          *)
(****************************************************************************)
(*                               more_words.v                               *)
(****************************************************************************)
(*              Formal Language Theory                                      *)
(*                                                                          *)
(*              Judicael Courant - Jean-Christophe Filliatre                *)
(*                                                                          *)
(*              Developped in V5.8  June-July 1993                          *)
(*              Ported     to V5.10 October 1994                            *)
(****************************************************************************)

Require Import Ensf.
Require Import Words.

Hint Unfold eqwordset .

Definition l_inclus (l1 l2 : wordset) : Prop := forall w : Word, l1 w -> l2 w.

Hint Unfold l_inclus.

Lemma refl_l_inclus : forall l1 : wordset, l_inclus l1 l1.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
auto.
Qed.
Hint Resolve refl_l_inclus.

Lemma trans_l_inclus :
 forall l1 l2 l3 : wordset,
 l_inclus l1 l2 -> l_inclus l2 l3 -> l_inclus l1 l3.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
auto.
Qed.


Definition l_egal (l1 l2 : wordset) : Prop :=
  l_inclus l1 l2 /\ l_inclus l2 l1.

Hint Unfold l_egal.

(*predicat equivalent a eqwordset*)
(*demonstration :                *)

Lemma equiv_l_egal_eqwordset :
 forall a b : wordset, l_egal a b <-> eqwordset a b.
(* Goal: forall a b : wordset, iff (l_egal a b) (eqwordset a b) *)
intros a b.
(* Goal: iff (l_egal a b) (eqwordset a b) *)
unfold iff in |- *.
(* Goal: and (forall _ : l_egal a b, eqwordset a b) (forall _ : eqwordset a b, l_egal a b) *)
split.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
intro Hyp; elim Hyp; auto.
(* Goal: forall _ : eqwordset a b, l_egal a b *)
intros Hyp.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
split; unfold l_inclus in |- *; intro w; elim (Hyp w); auto.
Qed.


Lemma refl_l_egal : forall l1 : wordset, l_egal l1 l1.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
auto.
Qed.
Hint Resolve refl_l_egal.




Section more_about_words.

Variable f : Elt -> Elt. 

Let wef := Word_ext f.

(* 
Lemma wef_cons : (a:Elt)(u:Word)(wef (cons a u))=(cons (f a) (wef u)).
Proof [a:Elt][u:Word](refl_equal Word (wef (cons a u))).
*)

Lemma wef_append :
 forall u v : Word, wef (Append u v) = Append (wef u) (wef v).
(* Goal: forall u v : Word, @eq Word (wef (Append u v)) (Append (wef u) (wef v)) *)
intros u v.
(* Goal: @eq Word (wef (Append u v)) (Append (wef u) (wef v)) *)
elim u.

(* Goal: @eq Word (cons x w) (cons x w) *)
(* Goal: and (@eq Elt (f x) e) (@eq Word (Word_ext f w) a) *)
	trivial.

(* Goal: forall _ : @eq Word (cons e a) (wef b), @ex Elt (fun x : Elt => @ex2 Word (fun w : Word => @eq Word (cons x w) b) (fun w : Word => and (@eq Elt (f x) e) (@eq Word (wef w) a))) *)
	unfold wef in |- *.
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (Word_ext f (Append w v)) (Append (Word_ext f w) (Word_ext f v))), @eq Word (Word_ext f (Append (cons e w) v)) (Append (Word_ext f (cons e w)) (Word_ext f v)) *)
	intros x w H.
(* Goal: @eq Word (Word_ext f (Append (cons x w) v)) (Append (Word_ext f (cons x w)) (Word_ext f v)) *)
	simpl in |- *.

(* Goal: @eq Word (cons (f x) (Word_ext f (Append w v))) (cons (f x) (Append (Word_ext f w) (Word_ext f v))) *)
	rewrite <- H.
(* Goal: @eq Word (cons (f x) (Word_ext f (Append w v))) (cons (f x) (Word_ext f (Append w v))) *)
	reflexivity.

Qed.

Lemma wef_nil : forall a : Word, wef a = nil -> a = nil.
(* Goal: forall (a : Word) (_ : @eq Word (wef a) nil), @eq Word a nil *)
intro a.
(* Goal: forall _ : @eq Word (wef a) nil, @eq Word a nil *)
case a.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
auto.

(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
unfold wef in |- *; simpl in |- *; intros x w H; discriminate H.

Qed.


Lemma wef_cons :
 forall (a b : Word) (e : Elt),
 cons e a = wef b ->
 exists x : Elt,
   ex2 (fun w : Word => cons x w = b) (fun w : Word => f x = e /\ wef w = a).

(* Goal: forall (a b : Word) (e : Elt) (_ : @eq Word (cons e a) (wef b)), @ex Elt (fun x : Elt => @ex2 Word (fun w : Word => @eq Word (cons x w) b) (fun w : Word => and (@eq Elt (f x) e) (@eq Word (wef w) a))) *)
intros a b e.
(* Goal: forall _ : @eq Word (cons e a) (wef b), @ex Elt (fun x : Elt => @ex2 Word (fun w : Word => @eq Word (cons x w) b) (fun w : Word => and (@eq Elt (f x) e) (@eq Word (wef w) a))) *)
unfold wef in |- *.
(* Goal: forall _ : @eq Word (cons e a) (Word_ext f b), @ex Elt (fun x : Elt => @ex2 Word (fun w : Word => @eq Word (cons x w) b) (fun w : Word => and (@eq Elt (f x) e) (@eq Word (Word_ext f w) a))) *)
case b.
(* Goal: forall _ : @eq Word (cons e a) (Word_ext f nil), @ex Elt (fun x : Elt => @ex2 Word (fun w : Word => @eq Word (cons x w) nil) (fun w : Word => and (@eq Elt (f x) e) (@eq Word (Word_ext f w) a))) *)
(* Goal: forall (e0 : Elt) (w : Word) (_ : @eq Word (cons e a) (Word_ext f (cons e0 w))), @ex Elt (fun x : Elt => @ex2 Word (fun w0 : Word => @eq Word (cons x w0) (cons e0 w)) (fun w0 : Word => and (@eq Elt (f x) e) (@eq Word (Word_ext f w0) a))) *)
	simpl in |- *; intro H; discriminate H.

(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (Word_ext f (Append w v)) (Append (Word_ext f w) (Word_ext f v))), @eq Word (Word_ext f (Append (cons e w) v)) (Append (Word_ext f (cons e w)) (Word_ext f v)) *)
	simpl in |- *; intros x w H.
(* Goal: @ex Elt (fun x0 : Elt => @ex2 Word (fun w0 : Word => @eq Word (cons x0 w0) (cons x w)) (fun w : Word => and (@eq Elt (f x0) e) (@eq Word (Word_ext f w) a))) *)
	exists x.
(* Goal: @ex2 Word (fun w0 : Word => @eq Word (cons x w0) (cons x w)) (fun w : Word => and (@eq Elt (f x) e) (@eq Word (Word_ext f w) a)) *)
	exists w.
(* Goal: @eq Word (cons x w) (cons x w) *)
(* Goal: and (@eq Elt (f x) e) (@eq Word (Word_ext f w) a) *)
		trivial.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
		injection H; auto.

Qed.

End more_about_words.

Hint Resolve wef_cons.

Lemma Append_assoc :
 forall a b c : Word, Append a (Append b c) = Append (Append a b) c.
(* Goal: forall a b c : Word, @eq Word (Append a (Append b c)) (Append (Append a b) c) *)
intros a b c. 
(* Goal: @eq Word (Append a (Append b c)) (Append (Append a b) c) *)
unfold Append in |- *.
(* Goal: forall _ : @eq Word (wef nil) nil, @eq Word nil nil *)
(* Goal: forall (e : Elt) (w : Word) (_ : @eq Word (wef (cons e w)) nil), @eq Word (cons e w) nil *)
elim a; auto.
Qed.
Hint Resolve Append_assoc.
