]> matita.cs.unibo.it Git - helm.git/blobdiff - matita/matita/lib/finite_lambda/terms_and_types.ma
finite_lambda restored
[helm.git] / matita / matita / lib / finite_lambda / terms_and_types.ma
diff --git a/matita/matita/lib/finite_lambda/terms_and_types.ma b/matita/matita/lib/finite_lambda/terms_and_types.ma
new file mode 100644 (file)
index 0000000..1ae47c2
--- /dev/null
@@ -0,0 +1,326 @@
+(*
+    ||M||  This file is part of HELM, an Hypertextual, Electronic        
+    ||A||  Library of Mathematics, developed at the Computer Science     
+    ||T||  Department of the University of Bologna, Italy.                     
+    ||I||                                                                 
+    ||T||  
+    ||A||  This file is distributed under the terms of the 
+    \   /  GNU General Public License Version 2        
+     \ /      
+      V_______________________________________________________________ *)
+
+include "basics/finset.ma".
+include "basics/star.ma".
+
+
+inductive FType (O:Type[0]): Type[0] ≝
+  | atom : O → FType O 
+  | arrow : FType O → FType O → FType O. 
+
+inductive T (O:Type[0]) (D:O → FinSet): Type[0] ≝
+  | Val: ∀o:O.carr (D o) → T O D        (* a value in a finset *)
+  | Rel: nat → T O D                    (* DB index, base is 0 *)
+  | App: T O D → T O D → T O D          (* function, argument *)
+  | Lambda: FType O → T O D → T O D     (* type, body *)
+  | Vec: FType O → list (T O D) → T O D (* type, body *)
+.
+
+let rec FinSet_of_FType O (D:O→FinSet) (ty:FType O) on ty : FinSet ≝
+  match ty with
+  [atom o ⇒ D o
+  |arrow ty1 ty2 ⇒ FinFun (FinSet_of_FType O D ty1) (FinSet_of_FType O D ty2)
+  ].
+
+(* size *)
+
+let rec size O D (M:T O D) on M ≝
+match M with
+  [Val o a ⇒ 1
+  |Rel n ⇒ 1
+  |App P Q ⇒ size O D P + size O D Q + 1
+  |Lambda Ty P ⇒ size O D P + 1
+  |Vec Ty v ⇒ foldr ?? (λx,a. size O D x + a) 0 v +1
+  ]
+.
+
+(* axiom pos_size: ∀M. 1 ≤ size M. *)
+
+theorem Telim_size: ∀O,D.∀P: T O D → Prop. 
+ (∀M. (∀N. size O D N < size O D M → P N) → P M) → ∀M. P M.
+#O #D #P #H #M (cut (∀p,N. size O D N = p → P N))
+  [2: /2/]
+#p @(nat_elim1 p) #m #H1 #N #sizeN @H #N0 #Hlt @(H1 (size O D N0)) //
+qed.
+
+lemma T_elim: 
+  ∀O: Type[0].∀D:O→FinSet.∀P:T O D→Prop.
+  (∀o:O.∀x:D o.P (Val O D o x)) →
+  (∀n:ℕ.P(Rel O D n)) →
+  (∀m,n:T O D.P m→P n→P (App O D m n)) →
+  (∀Ty:FType O.∀m:T O D.P m→P(Lambda O D Ty m)) →
+  (∀Ty:FType O.∀v:list (T O D).
+     (∀x:T O D. mem ? x v → P x) → P(Vec O D Ty v)) →
+  ∀x:T O D.P x.
+#O #D #P #Hval #Hrel #Happ #Hlam #Hvec @Telim_size #x cases x //
+  [ (* app *) #m #n #Hind @Happ @Hind // /2 by le_minus_to_plus/
+  | (* lam *) #ty #m #Hind @Hlam @Hind normalize // 
+  | (* vec *) #ty #v #Hind @Hvec #x lapply Hind elim v
+    [#Hind normalize *
+    |#hd #tl #Hind1 #Hind2 * 
+      [#Hx >Hx @Hind2 normalize //
+      |@Hind1 #N #H @Hind2 @(lt_to_le_to_lt … H) normalize //
+      ]
+    ]
+  ]
+qed.
+
+(* since we only consider beta reduction with closed arguments we could avoid
+lifting. We define it for the sake of generality *)
+        
+(* arguments: k is the nesting depth (starts from 0), p is the lift 
+let rec lift O D t k p on t ≝ 
+  match t with 
+    [ Val o a ⇒ Val O D o a
+    | Rel n ⇒ if (leb k n) then Rel O D (n+p) else Rel O D n
+    | App m n ⇒ App O D (lift O D m k p) (lift O D n k p)
+    | Lambda Ty n ⇒ Lambda O D Ty (lift O D n (S k) p)
+    | Vec Ty v ⇒ Vec O D Ty (map ?? (λx. lift O D x k p) v) 
+    ].
+
+notation "↑ ^ n ( M )" non associative with precedence 40 for @{'Lift 0 $n $M}.
+notation "↑ _ k ^ n ( M )" non associative with precedence 40 for @{'Lift $n $k $M}.
+
+interpretation "Lift" 'Lift n k M = (lift ?? M k n). 
+
+let rec subst O D t k s on t ≝ 
+  match t with 
+    [ Val o a ⇒ Val O D o a 
+    | Rel n ⇒ if (leb k n) then
+        (if (eqb k n) then lift O D s 0 n else Rel O D (n-1)) 
+        else(Rel O D n)
+    | App m n ⇒ App O D (subst O D m k s) (subst O D n k s)
+    | Lambda T n ⇒ Lambda O D T (subst O D n (S k) s)
+    | Vec T v ⇒ Vec O D T (map ?? (λx. subst O D x k s) v) 
+    ].
+*)
+
+(* simplified version of subst, assuming the argument s is closed *)
+
+let rec subst O D t k s on t ≝ 
+  match t with 
+    [ Val o a ⇒ Val O D o a 
+    | Rel n ⇒ if (leb k n) then
+        (if (eqb k n) then (* lift O D s 0 n*) s else Rel O D (n-1)) 
+        else(Rel O D n)
+    | App m n ⇒ App O D (subst O D m k s) (subst O D n k s)
+    | Lambda T n ⇒ Lambda O D T (subst O D n (S k) s)
+    | Vec T v ⇒ Vec O D T (map ?? (λx. subst O D x k s) v) 
+    ].
+(* notation "hvbox(M break [ k ≝ N ])" 
+   non associative with precedence 90
+   for @{'Subst1 $M $k $N}. *)
+interpretation "Subst" 'Subst1 M k N = (subst M k N). 
+
+(*
+lemma subst_rel1: ∀O,D,A.∀k,i. i < k → 
+  (Rel O D i) [k ≝ A] = Rel O D i.
+#A #k #i normalize #ltik >(lt_to_leb_false … ltik) //
+qed.
+
+lemma subst_rel2: ∀O,D, A.∀k. 
+  (Rel k) [k ≝ A] = lift A 0 k.
+#A #k normalize >(le_to_leb_true k k) // >(eq_to_eqb_true … (refl …)) //
+qed.
+
+lemma subst_rel3: ∀A.∀k,i. k < i → 
+  (Rel i) [k ≝ A] = Rel (i-1).
+#A #k #i normalize #ltik >(le_to_leb_true k i) /2/ 
+>(not_eq_to_eqb_false k i) // @lt_to_not_eq //
+qed. *)
+
+
+(* closed terms ????
+let rec closed_k O D (t: T O D) k on t ≝ 
+  match t with 
+    [ Val o a ⇒ True
+    | Rel n ⇒ n < k 
+    | App m n ⇒ (closed_k O D m k) ∧ (closed_k O D n k)
+    | Lambda T n ⇒ closed_k O D n (k+1)
+    | Vec T v ⇒ closed_list O D v k
+    ]
+    
+and closed_list O D (l: list (T O D)) k on l ≝
+  match l with
+    [ nil ⇒ True
+    | cons hd tl ⇒ closed_k O D hd k ∧ closed_list O D tl k
+    ]
+. *)
+
+inductive is_closed (O:Type[0]) (D:O→FinSet): nat → T O D → Prop ≝
+| cval : ∀k,o,a.is_closed O D k (Val O D o a)
+| crel : ∀k,n. n < k → is_closed O D k (Rel O D n)
+| capp : ∀k,m,n. is_closed O D k m → is_closed O D k n → 
+           is_closed O D k (App O D m n)
+| clam : ∀T,k,m. is_closed O D (S k) m → is_closed O D k (Lambda O D T m)
+| cvec:  ∀T,k,v. (∀m. mem ? m v → is_closed O D k m) → 
+           is_closed O D k (Vec O D T v).
+      
+lemma is_closed_rel: ∀O,D,n,k.
+  is_closed O D k (Rel O D n) → n < k.
+#O #D #n #k #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct //
+  |#k0 #M #N #_ #_ #_ #_ #_ #H destruct
+  |#T #k0 #M #_ #_ #_ #H destruct
+  |#T #k0 #v #_ #_ #_ #H destruct
+  ]
+qed.
+  
+lemma is_closed_app: ∀O,D,k,M, N.
+  is_closed O D k (App O D M N) → is_closed O D k M ∧ is_closed O D k N.
+#O #D #k #M #N #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct 
+  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct % //
+  |#T #k0 #M #_ #_ #_ #H destruct
+  |#T #k0 #v #_ #_ #_ #H destruct
+  ]
+qed.
+  
+lemma is_closed_lam: ∀O,D,k,ty,M.
+  is_closed O D k (Lambda O D ty M) → is_closed O D (S k) M.
+#O #D #k #ty #M #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct 
+  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct 
+  |#T #k0 #M1 #HM1 #_ #_ #H1 destruct //
+  |#T #k0 #v #_ #_ #_ #H destruct
+  ]
+qed.
+
+lemma is_closed_vec: ∀O,D,k,ty,v.
+  is_closed O D k (Vec O D ty v) → ∀m. mem ? m v → is_closed O D k m.
+#O #D #k #ty #M #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct 
+  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct 
+  |#T #k0 #M1 #HM1 #_ #_ #H1 destruct
+  |#T #k0 #v #Hv #_ #_ #H1 destruct @Hv
+  ]
+qed.
+
+lemma is_closed_S: ∀O,D,M,m.
+  is_closed O D m M → is_closed O D (S m) M.
+#O #D #M #m #H elim H //
+  [#k #n0 #Hlt @crel @le_S //
+  |#k #P #Q #HP #HC #H1 #H2 @capp //
+  |#ty #k #P #HP #H1 @clam //
+  |#ty #k #v #Hind #Hv @cvec @Hv
+  ]
+qed.
+
+lemma is_closed_mono: ∀O,D,M,m,n. m ≤ n →
+  is_closed O D m M → is_closed O D n M.
+#O #D #M #m #n #lemn elim lemn // #i #j #H #H1 @is_closed_S @H @H1
+qed.
+  
+  
+(*** properties of lift and subst ***)
+
+(*
+lemma lift_0: ∀O,D.∀t:T O D.∀k. lift O D t k 0 = t.
+#O #D #t @(T_elim … t) normalize // 
+  [#n #k cases (leb k n) normalize // 
+  |#o #v #Hind #k @eq_f lapply Hind -Hind elim v // 
+   #hd #tl #Hind #Hind1 normalize @eq_f2 
+    [@Hind1 %1 //|@Hind #x #Hx @Hind1 %2 //]
+  ]
+qed.
+
+lemma lift_closed: ∀O,D.∀t:T O D.∀k,p. 
+  is_closed O D k t → lift O D t k p = t.
+#O #D #t @(T_elim … t) normalize // 
+  [#n #k #p #H >(not_le_to_leb_false … (lt_to_not_le … (is_closed_rel … H))) //
+  |#M #N #HindM #HindN #k #p #H lapply (is_closed_app … H) * #HcM #HcN
+   >(HindM … HcM) >(HindN … HcN) //
+  |#ty #M #HindM #k #p #H lapply (is_closed_lam … H) -H #H >(HindM … H) //
+  |#ty #v #HindM #k #p #H lapply (is_closed_vec … H) -H #H @eq_f 
+   cut (∀m. mem ? m v → lift O D m k p = m)
+    [#m #Hmem @HindM [@Hmem | @H @Hmem]] -HindM
+   elim v // #a #tl #Hind #H1 normalize @eq_f2
+    [@H1 %1 //|@Hind #m #Hmem @H1 %2 @Hmem]
+  ]
+qed.  
+
+*)
+
+lemma subst_closed: ∀O,D,M,N,k,i. k ≤ i → 
+  is_closed O D k M → subst O D M i N = M.
+#O #D #M @(T_elim … M)
+  [#o #a normalize //
+  |#n #N #k #j #Hlt #Hc lapply (is_closed_rel … Hc) #Hnk normalize 
+   >not_le_to_leb_false [2:@lt_to_not_le @(lt_to_le_to_lt … Hnk Hlt)] //
+  |#P #Q #HindP #HindQ #N #k #i #ltki #Hc lapply (is_closed_app … Hc) * 
+   #HcP #HcQ normalize >(HindP … ltki HcP) >(HindQ … ltki HcQ) //
+  |#ty #P #HindP #N #k #i #ltki #Hc lapply (is_closed_lam … Hc)  
+   #HcP normalize >(HindP … HcP) // @le_S_S @ltki
+  |#ty #v #Hindv #N #k #i #ltki #Hc lapply (is_closed_vec … Hc)  
+   #Hcv normalize @eq_f 
+   cut (∀m:T O D.mem (T O D) m v→ subst O D m i N=m)
+    [#m #Hmem @(Hindv … Hmem N … ltki) @Hcv @Hmem] 
+   elim v // #a #tl #Hind #H normalize @eq_f2
+    [@H %1 //| @Hind #Hmem #Htl @H %2 @Htl]
+  ]
+qed.
+
+lemma subst_lemma:  ∀O,D,A,B,C,k,i. is_closed O D k B → is_closed O D i C →
+  subst O D (subst O D A i B) (k+i) C =
+  subst O D (subst O D A (k+S i) C) i B.
+#O #D #A #B #C #k @(T_elim … A) normalize 
+  [//
+  |#n #i #HBc #HCc @(leb_elim i n) #Hle 
+    [@(eqb_elim i n) #eqni
+      [<eqni >(lt_to_leb_false (k+(S i)) i) // normalize 
+       >(subst_closed … HBc) // >le_to_leb_true // >eq_to_eqb_true // 
+      |(cut (i < n)) 
+        [cases (le_to_or_lt_eq … Hle) // #eqin @False_ind /2/] #ltin 
+       (cut (0 < n)) [@(le_to_lt_to_lt … ltin) //] #posn
+       normalize @(leb_elim (k+i) (n-1)) #nk
+        [@(eqb_elim (k+i) (n-1)) #H normalize
+          [cut (k+(S i) = n); [/2 by S_pred/] #H1
+           >(le_to_leb_true (k+(S i)) n) /2/
+           >(eq_to_eqb_true … H1) normalize >(subst_closed … HCc) //
+          |(cut (k+i < n-1)) [@not_eq_to_le_to_lt; //] #Hlt 
+           >(le_to_leb_true (k+(S i)) n) normalize
+            [>(not_eq_to_eqb_false (k+(S i)) n) normalize
+              [>le_to_leb_true [2:@lt_to_le @(le_to_lt_to_lt … Hlt) //]
+               >not_eq_to_eqb_false // @lt_to_not_eq @(le_to_lt_to_lt … Hlt) //
+              |@(not_to_not … H) #Hn /2 by plus_minus/ 
+              ]  
+            |<plus_n_Sm @(lt_to_le_to_lt … Hlt) //
+            ]
+          ]
+        |>(not_le_to_leb_false (k+(S i)) n) normalize
+          [>(le_to_leb_true … Hle) >(not_eq_to_eqb_false … eqni) // 
+          |@(not_to_not … nk) #H @le_plus_to_minus_r //
+          ]
+        ] 
+      ]
+    |(cut (n < k+i)) [@(lt_to_le_to_lt ? i) /2 by not_le_to_lt/] #ltn 
+     >not_le_to_leb_false [2: @lt_to_not_le @(transitive_lt …ltn) //] normalize 
+     >not_le_to_leb_false [2: @lt_to_not_le //] normalize
+     >(not_le_to_leb_false … Hle) // 
+    ] 
+  |#M #N #HindM #HindN #i #HBC #HCc @eq_f2 [@HindM // |@HindN //]
+  |#ty #M #HindM #i #HBC #HCc @eq_f >plus_n_Sm >plus_n_Sm @HindM // 
+   @is_closed_S //
+  |#ty #v #Hindv #i #HBC #HCc @eq_f 
+   cut (∀m.mem ? m v → subst O D (subst O D m i B) (k+i) C = 
+          subst O D (subst O D m (k+S i) C) i B)
+    [#m #Hmem @Hindv //] -Hindv elim v normalize [//]
+   #a #tl #Hind #H @eq_f2 [@H %1 // | @Hind #m #Hmem @H %2 //]
+  ]
+qed.
+
+