(* $Id: Apsig.v,v 1.2 1999/10/05 10:35:33 boulme Exp $ *)
(* An operation for expressing the "difference" between 2 records *)

Set Implicit Arguments.
Unset Strict Implicit.

Require Export Subsig.

Section Apsig.

Variable A : Set.

Definition apsig_pre :
  forall (l1 l2 : list A) (s1 : sigtel l1) (s2 : sigtel l2)
    (H : prefix (eq (A:=A)) l1 l2),
  presub H s1 s2 -> impltel s2 -> sigtel (extractO_pre H). 
  fix 6; intros l1 l2 s1 s2 Hc H; case H; simpl in |- *;
   clear H Hc s2 s1 l2 l1; auto with sigtel.
  intros a l1 l2 T f g Hc H i; case i; intros x i';
   apply apsig_pre with (s1 := f x) (s2 := g x); auto with sigtel.
Defined.

Transparent eq_rec sym_eq f_equal trans_eq.
Lemma subsig_flatsig_apsig_pre_l :
 forall (l1 l2 : list A) (s1 : sigtel l1) (s2 : sigtel l2)
   (H : prefix (eq (A:=A)) l1 l2) (H1 : presub H s1 s2),
 subsig (prefix_app_extractO (refl_equal (A:=A)) (sym_eq (A:=A)) H)
   (flatsig (fun i => apsig_pre H1 i)) s1.
  fix 6; intros l1 l2 s1 s2 Hp H; case H; clear H Hp s2 s1 l2 l1;
   simpl in |- *; auto with sigtel.
Defined.
Hint Resolve subsig_flatsig_apsig_pre_l: sigtel.

Definition apsig_sig :
  forall (l1 l2 : list A) (s1 : sigtel l1) (s2 : sigtel l2)
    (H : contO (eq (A:=A)) l1 l2) (H1 : subsig H s1 s2),
  sigT
    (fun
       f : impltel s2 ->
           sigtel (extractO (refl_equal (A:=A)) (trans_eq (A:=A)) H) =>
     subsig
       (contO_app_extractO (refl_equal (A:=A)) (trans_eq (A:=A))
          (sym_eq (A:=A)) H) (flatsig (fun i => f i)) s1).

  intros l1 l2 s1 s2 H H1; elim H1; simpl in |- *; clear H1 H s2 s1 l2 l1.

  intros l s; split with (x := fun _ : unit => s); auto with sigtel.

  intros a l1 l2 T f g Hc H1 HR;
   split
    with
      (x := fun i : impltel (Csig a g) => projT1 (HR (dprojT1 i)) (dprojT2 i));
   simpl in |- *; apply subsig_C; intro x; case (HR x); 
   auto.

  intros a l1 l2 T f s Hc H HR;
   split
    with (x := fun i : impltel s => Csig a (fun x : T => projT1 (HR x) i));
   simpl in |- *;
   apply
    subtel_Csig_flatsig
     with (f := fun (x : T) (i : impltel s) => projT1 (HR x) i); 
   intro x; case (HR x); simpl in |- *; auto. 

  intros a1 a2 l1 l2 T1 T2 f g Hc H1 HR.
  split
   with
     (x := fun
             i : impltel
                   (Csig a2 (fun y : T2 => Csig a1 (fun x : T1 => g y x))) =>
           projT1 (HR (dprojT1 (dprojT2 i)) (dprojT1 i))
             (dprojT2 (dprojT2 i))); simpl in |- *;
   apply
    subsig_swap
     with
       (f := fun (y : T2) (x : T1) =>
             flatsig (fun i : impltel (g y x) => projT1 (HR x y) i));
   intros y x; case (HR x y); simpl in |- *; auto.


  intros l1 l2 l3 s1 s2 s3 Hc1 Hc2 H1 HR1 H2 HR2; case HR1; case HR2.
   intros g H5 f H4. 
   split
    with
      (x := apsig_pre
              (presub_trans
                 (presub_flatsig
                    (fun i : impltel (flatsig (fun i' => g i')) =>
                     f (coerce_impltel H5 i)))
                 (presub_flatsig (fun i' => g i')))). 
  apply subsig_trans with (A := A) (s2 := flatsig (fun i => f i));
   auto with sigtel.
  apply
   subsig_trans
    with
      (A := A)
      (s2 := flatsig
               (fun i : impltel (flatsig (fun i' => g i')) =>
                f (coerce_impltel H5 i))); auto with sigtel.
Defined.

End Apsig.









