include "basics/lists/listb.ma". definition bool_to_Prop : bool → Prop ≝ λb. match b with [ true ⇒ True | false ⇒ False ]. coercion bool_to_Prop: ∀b:bool. Prop ≝ bool_to_Prop on _b:bool to Type[0]. record test (A:Type[0]) (B:Type[0]) (C:Type[0]) : Type[0] ≝ { a:A; b:B; c:C }. inductive tag : Type[0] := a : tag | b : tag | c : tag. definition tag_of_pos : nat → tag ≝ λn. if eqb n 0 then a else if eqb n 1 then b else c. definition type_of_tag : tag → Type[0] ≝ λt. match t with [ a ⇒ nat | b ⇒ bool | c ⇒ nat ]. definition eq_tag : tag → tag → bool ≝ λt1,t2. match t1 with [ a => match t2 with [a => true | _ => false] | b => match t2 with [b => true | _ => false] | c => match t2 with [c => true | _ => false]]. definition Tag : DeqSet ≝ mk_DeqSet tag eq_tag ?. ** normalize /2/ % #abs destruct qed. let rec Types (n:nat) on n : Type[1] ≝ match n with [ O ⇒ Type[0] | S m ⇒ Type[0] → Types m ]. let rec record_ty0 (l: list tag) (n:nat) on n : Types n → Type[0] ≝ match n return λn. Types n → Type[0] with [ O ⇒ λr:Type[0].r | S m ⇒ λhd:Type[0] → Types m. let tag ≝ tag_of_pos m in if memb Tag tag l then record_ty0 l m (hd (type_of_tag tag)) else record_ty0 l m (hd unit)]. definition record_ty : list tag → Type[0] ≝ λl. record_ty0 l 3 test. coercion record_ty : ∀l:list tag. Type[0] ≝ record_ty on _l: list tag to Type[0]. XXX let rec mk_record_ty (l: list tag) (n:nat) on n : Type[0] ≝ match n with [ O ⇒ l | ]. let rec mk_record (l: list (Σt:tag. type_of_tag t)) (n:nat) on n : mk_record_ty n → l ≝ match n return with [ ]. definition tag_of_expr : ∀E:Type[0]. expr E -> tag := λE,e. match e with [ Num _ => num | Plus _ _ => plus | Mul _ _ => mul ]. (*definition is_a : ∀E: Type[0]. tag -> expr E -> Prop ≝ λE,t,e. eq_tag t (tag_of_expr \ldots e).*) definition is_in : ∀E: Type[0]. list tag -> expr E -> bool ≝ λE,l,e. memb Tag (tag_of_expr ? e) l. record sub_expr (l: list tag) (E: Type[0]) : Type[0] ≝ { se_el :> expr E; se_el_in: is_in … l se_el }. coercion sub_expr : ∀l:list tag. Type[0] → Type[0] ≝ sub_expr on _l: list tag to Type[0] → Type[0]. coercion mk_sub_expr : ∀l:list tag.∀E.∀e:expr E. ∀p:is_in ? l e.sub_expr l E ≝ mk_sub_expr on e:expr ? to sub_expr ? ?. let rec sublist (S:DeqSet) (l1:list S) (l2:list S) on l1 : bool ≝ match l1 with [ nil ⇒ true | cons hd tl ⇒ memb S hd l2 ∧ sublist S tl l2 ]. lemma sublist_hd_tl_to_memb: ∀S:DeqSet. ∀hd:S. ∀tl:list S. ∀l2. sublist S (hd::tl) l2 → memb S hd l2. #S #hd #tl #l2 normalize cases (hd ∈ l2) normalize // qed. lemma sublist_hd_tl_to_sublist: ∀S:DeqSet. ∀hd:S. ∀tl:list S. ∀l2. sublist S (hd::tl) l2 → sublist S tl l2. #S #hd #tl #l2 normalize cases (hd ∈ l2) normalize // #H cases H qed. lemma sublist_insert_snd_pos: ∀S:DeqSet. ∀x,y:S. ∀l1,l2:list S. sublist S l1 (x::l2) → sublist S l1 (x::y::l2). #S #x #y #l1 elim l1 [//] #hd #tl #IH #l2 #H lapply (sublist_hd_tl_to_sublist … H) #K whd in match (sublist ???); >(?:hd∈x::y::l2 = true) /2/ lapply (sublist_hd_tl_to_memb … H) normalize cases (hd==x) normalize // cases (hd==y) normalize // cases (hd∈l2) // #H cases H qed. lemma sublist_tl_hd_tl: ∀S:DeqSet. ∀hd:S. ∀tl:list S. sublist S tl (hd::tl). #S #hd #tl elim tl try % #hd' #tl' #IH whd in match (sublist ???); whd in match (hd' ∈ hd::?::?); cases (hd'==hd) whd in match (hd' ∈ ?::?); >(\b ?) try % normalize lapply (sublist_insert_snd_pos … hd' … IH) cases (sublist ???) // qed. lemma sublist_refl: ∀S:DeqSet. ∀l: list S. sublist S l l. #S #l elim l [//] #hd #tl #IH normalize >(\b ?) // qed. let rec sub_expr_elim_type (E:Type[0]) (fixed_l: list tag) (orig: fixed_l E) (Q: fixed_l E → Prop) (l: list tag) on l : sublist Tag l fixed_l → Prop ≝ match l return λl. sublist Tag l fixed_l → Prop with [ nil ⇒ λH. Q orig | cons hd tl ⇒ λH. let tail_call ≝ sub_expr_elim_type E fixed_l orig Q tl ? in match hd return λt. memb Tag t fixed_l → Prop with [ num ⇒ λH. (∀n. Q (Num … n)) → tail_call | plus ⇒ λH. (∀x,y. Q (Plus … x y)) → tail_call | mul ⇒ λH. (∀x,y. Q (Mul … x y)) → tail_call ] (sublist_hd_tl_to_memb Tag hd tl fixed_l H)]. /2/ qed. lemma sub_expr_elim0: ∀E:Type[0]. ∀l: list tag. ∀x: l E. ∀Q: l E → Prop. ∀l',H. (∀y:l E. ¬ is_in … l' y → Q y) → sub_expr_elim_type E l x Q l' H. #E #l #x #Q #l' elim l' /2/ #hd #tl #IH cases hd #H #INV whd #P0 @IH ** /2/ qed. theorem sub_expr_elim: ∀E:Type[0]. ∀l: list tag. ∀x: l E. ∀Q: l E → Prop. sub_expr_elim_type E l x Q l ?. [2:// | #E #l #x #Q @sub_expr_elim0 * #y #H #NH cases (?: False) cases (is_in E l y) in H NH; // qed. (**************************************) definition eval_additive_expr: ∀E:Type[0]. (E → nat) → [plus] E → nat ≝ λE,f,e. match e return λe. is_in … [plus] e → nat with [ Plus x y ⇒ λH. f x + f y | _ ⇒ λH:False. ? ] (se_el_in ?? e). elim H qed. definition eval_multiplicative_expr: ∀E:Type[0]. (E → nat) → [mul] E → nat ≝ λE,f,e. match e return λe. is_in … [mul] e → nat with [ Mul x y ⇒ λH. f x * f y | _ ⇒ λH:False. ? ] (se_el_in ?? e). elim H qed. definition eval_additive_multiplicative_expr: ∀E:Type[0]. (E → nat) → [plus;mul] E → nat ≝ λE,f,e. match e return λe. is_in … [plus;mul] e → nat with [ Plus x y ⇒ λH. eval_additive_expr … f (Plus ? x y) | Mul x y ⇒ λH. eval_multiplicative_expr E f (Mul ? x y) | _ ⇒ λH:False. ? ] (se_el_in ?? e). [2,3: % | elim H] qed. definition eval_additive_multiplicative_constant_expr: ∀E:Type[0]. (E → nat) → [plus;mul;num] E → nat ≝ λE,f,e. match e return λe. is_in … [plus;mul;num] e → nat with [ Plus x y ⇒ λH. eval_additive_expr … f (Plus ? x y) | Mul x y ⇒ λH. eval_multiplicative_expr E f (Mul ? x y) | Num n ⇒ λH. n ] (se_el_in ?? e). % qed. (*CSC: not accepted :-( inductive expr_no_const : Type[0] ≝ K : [plus;mul] expr_no_const → expr_no_const. *) inductive final_expr : Type[0] ≝ K : expr final_expr → final_expr. coercion K. let rec eval_final_expr e on e : nat ≝ match e with [ K e' ⇒ eval_additive_multiplicative_constant_expr final_expr eval_final_expr e']. cases e' try #x try #y % qed. example test: eval_final_expr (K (Mul ? (Num ? 2) (Num ? 3))) = 6. % qed.