1 (* Title: CCL/types |
1 (* Title: CCL/Type.ML |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Martin Coen, Cambridge University Computer Laboratory |
3 Author: Martin Coen, Cambridge University Computer Laboratory |
4 Copyright 1992 University of Cambridge |
4 Copyright 1992 University of Cambridge |
5 |
|
6 For types.thy. |
|
7 *) |
5 *) |
8 |
|
9 open Type; |
|
10 |
6 |
11 val simp_type_defs = [Subtype_def,Unit_def,Bool_def,Plus_def,Sigma_def,Pi_def, |
7 val simp_type_defs = [Subtype_def,Unit_def,Bool_def,Plus_def,Sigma_def,Pi_def, |
12 Lift_def,Tall_def,Tex_def]; |
8 Lift_def,Tall_def,Tex_def]; |
13 val ind_type_defs = [Nat_def,List_def]; |
9 val ind_type_defs = [Nat_def,List_def]; |
14 |
10 |
15 val simp_data_defs = [one_def,inl_def,inr_def]; |
11 val simp_data_defs = [one_def,inl_def,inr_def]; |
16 val ind_data_defs = [zero_def,succ_def,nil_def,cons_def]; |
12 val ind_data_defs = [zero_def,succ_def,nil_def,cons_def]; |
17 |
13 |
18 goal Set.thy "A <= B <-> (ALL x. x:A --> x:B)"; |
14 goal (the_context ()) "A <= B <-> (ALL x. x:A --> x:B)"; |
19 by (fast_tac set_cs 1); |
15 by (fast_tac set_cs 1); |
20 qed "subsetXH"; |
16 qed "subsetXH"; |
21 |
17 |
22 (*** Exhaustion Rules ***) |
18 (*** Exhaustion Rules ***) |
23 |
19 |
24 fun mk_XH_tac thy defs rls s = prove_goalw thy defs s (fn _ => [cfast_tac rls 1]); |
20 fun mk_XH_tac thy defs rls s = prove_goalw thy defs s (fn _ => [cfast_tac rls 1]); |
25 val XH_tac = mk_XH_tac Type.thy simp_type_defs []; |
21 val XH_tac = mk_XH_tac (the_context ()) simp_type_defs []; |
26 |
22 |
27 val EmptyXH = XH_tac "a : {} <-> False"; |
23 val EmptyXH = XH_tac "a : {} <-> False"; |
28 val SubtypeXH = XH_tac "a : {x:A. P(x)} <-> (a:A & P(a))"; |
24 val SubtypeXH = XH_tac "a : {x:A. P(x)} <-> (a:A & P(a))"; |
29 val UnitXH = XH_tac "a : Unit <-> a=one"; |
25 val UnitXH = XH_tac "a : Unit <-> a=one"; |
30 val BoolXH = XH_tac "a : Bool <-> a=true | a=false"; |
26 val BoolXH = XH_tac "a : Bool <-> a=true | a=false"; |
40 |
36 |
41 val case_rls = XH_to_Es XHs; |
37 val case_rls = XH_to_Es XHs; |
42 |
38 |
43 (*** Canonical Type Rules ***) |
39 (*** Canonical Type Rules ***) |
44 |
40 |
45 fun mk_canT_tac thy xhs s = prove_goal thy s |
41 fun mk_canT_tac thy xhs s = prove_goal thy s |
46 (fn prems => [fast_tac (set_cs addIs (prems @ (xhs RL [iffD2]))) 1]); |
42 (fn prems => [fast_tac (set_cs addIs (prems @ (xhs RL [iffD2]))) 1]); |
47 val canT_tac = mk_canT_tac Type.thy XHs; |
43 val canT_tac = mk_canT_tac (the_context ()) XHs; |
48 |
44 |
49 val oneT = canT_tac "one : Unit"; |
45 val oneT = canT_tac "one : Unit"; |
50 val trueT = canT_tac "true : Bool"; |
46 val trueT = canT_tac "true : Bool"; |
51 val falseT = canT_tac "false : Bool"; |
47 val falseT = canT_tac "false : Bool"; |
52 val lamT = canT_tac "[| !!x. x:A ==> b(x):B(x) |] ==> lam x. b(x) : Pi(A,B)"; |
48 val lamT = canT_tac "[| !!x. x:A ==> b(x):B(x) |] ==> lam x. b(x) : Pi(A,B)"; |
57 val canTs = [oneT,trueT,falseT,pairT,lamT,inlT,inrT]; |
53 val canTs = [oneT,trueT,falseT,pairT,lamT,inlT,inrT]; |
58 |
54 |
59 (*** Non-Canonical Type Rules ***) |
55 (*** Non-Canonical Type Rules ***) |
60 |
56 |
61 local |
57 local |
62 val lemma = prove_goal Type.thy "[| a:B(u); u=v |] ==> a : B(v)" |
58 val lemma = prove_goal (the_context ()) "[| a:B(u); u=v |] ==> a : B(v)" |
63 (fn prems => [cfast_tac prems 1]); |
59 (fn prems => [cfast_tac prems 1]); |
64 in |
60 in |
65 fun mk_ncanT_tac thy defs top_crls crls s = prove_goalw thy defs s |
61 fun mk_ncanT_tac thy defs top_crls crls s = prove_goalw thy defs s |
66 (fn major::prems => [(resolve_tac ([major] RL top_crls) 1), |
62 (fn major::prems => [(resolve_tac ([major] RL top_crls) 1), |
67 (REPEAT_SOME (eresolve_tac (crls @ [exE,bexE,conjE,disjE]))), |
63 (REPEAT_SOME (eresolve_tac (crls @ [exE,bexE,conjE,disjE]))), |
68 (ALLGOALS (asm_simp_tac term_ss)), |
64 (ALLGOALS (asm_simp_tac term_ss)), |
69 (ALLGOALS (ares_tac (prems RL [lemma]) ORELSE' |
65 (ALLGOALS (ares_tac (prems RL [lemma]) ORELSE' |
70 etac bspec )), |
66 etac bspec )), |
71 (safe_tac (ccl_cs addSIs prems))]); |
67 (safe_tac (ccl_cs addSIs prems))]); |
72 end; |
68 end; |
73 |
69 |
74 val ncanT_tac = mk_ncanT_tac Type.thy [] case_rls case_rls; |
70 val ncanT_tac = mk_ncanT_tac (the_context ()) [] case_rls case_rls; |
75 |
71 |
76 val ifT = ncanT_tac |
72 val ifT = ncanT_tac |
77 "[| b:Bool; b=true ==> t:A(true); b=false ==> u:A(false) |] ==> \ |
73 "[| b:Bool; b=true ==> t:A(true); b=false ==> u:A(false) |] ==> \ |
78 \ if b then t else u : A(b)"; |
74 \ if b then t else u : A(b)"; |
79 |
75 |
80 val applyT = ncanT_tac |
76 val applyT = ncanT_tac |
81 "[| f : Pi(A,B); a:A |] ==> f ` a : B(a)"; |
77 "[| f : Pi(A,B); a:A |] ==> f ` a : B(a)"; |
82 |
78 |
83 val splitT = ncanT_tac |
79 val splitT = ncanT_tac |
84 "[| p:Sigma(A,B); !!x y. [| x:A; y:B(x); p=<x,y> |] ==> c(x,y):C(<x,y>) |] ==> \ |
80 "[| p:Sigma(A,B); !!x y. [| x:A; y:B(x); p=<x,y> |] ==> c(x,y):C(<x,y>) |] ==> \ |
85 \ split(p,c):C(p)"; |
81 \ split(p,c):C(p)"; |
86 |
82 |
87 val whenT = ncanT_tac |
83 val whenT = ncanT_tac |
88 "[| p:A+B; !!x.[| x:A; p=inl(x) |] ==> a(x):C(inl(x)); \ |
84 "[| p:A+B; !!x.[| x:A; p=inl(x) |] ==> a(x):C(inl(x)); \ |
89 \ !!y.[| y:B; p=inr(y) |] ==> b(y):C(inr(y)) |] ==> \ |
85 \ !!y.[| y:B; p=inr(y) |] ==> b(y):C(inr(y)) |] ==> \ |
90 \ when(p,a,b) : C(p)"; |
86 \ when(p,a,b) : C(p)"; |
91 |
87 |
92 val ncanTs = [ifT,applyT,splitT,whenT]; |
88 val ncanTs = [ifT,applyT,splitT,whenT]; |
94 (*** Subtypes ***) |
90 (*** Subtypes ***) |
95 |
91 |
96 val SubtypeD1 = standard ((SubtypeXH RS iffD1) RS conjunct1); |
92 val SubtypeD1 = standard ((SubtypeXH RS iffD1) RS conjunct1); |
97 val SubtypeD2 = standard ((SubtypeXH RS iffD1) RS conjunct2); |
93 val SubtypeD2 = standard ((SubtypeXH RS iffD1) RS conjunct2); |
98 |
94 |
99 val prems = goal Type.thy |
95 val prems = goal (the_context ()) |
100 "[| a:A; P(a) |] ==> a : {x:A. P(x)}"; |
96 "[| a:A; P(a) |] ==> a : {x:A. P(x)}"; |
101 by (REPEAT (resolve_tac (prems@[SubtypeXH RS iffD2,conjI]) 1)); |
97 by (REPEAT (resolve_tac (prems@[SubtypeXH RS iffD2,conjI]) 1)); |
102 qed "SubtypeI"; |
98 qed "SubtypeI"; |
103 |
99 |
104 val prems = goal Type.thy |
100 val prems = goal (the_context ()) |
105 "[| a : {x:A. P(x)}; [| a:A; P(a) |] ==> Q |] ==> Q"; |
101 "[| a : {x:A. P(x)}; [| a:A; P(a) |] ==> Q |] ==> Q"; |
106 by (REPEAT (resolve_tac (prems@[SubtypeD1,SubtypeD2]) 1)); |
102 by (REPEAT (resolve_tac (prems@[SubtypeD1,SubtypeD2]) 1)); |
107 qed "SubtypeE"; |
103 qed "SubtypeE"; |
108 |
104 |
109 (*** Monotonicity ***) |
105 (*** Monotonicity ***) |
114 |
110 |
115 Goal "mono(%X. A)"; |
111 Goal "mono(%X. A)"; |
116 by (REPEAT (ares_tac [monoI,subset_refl] 1)); |
112 by (REPEAT (ares_tac [monoI,subset_refl] 1)); |
117 qed "constM"; |
113 qed "constM"; |
118 |
114 |
119 val major::prems = goal Type.thy |
115 val major::prems = goal (the_context ()) |
120 "mono(%X. A(X)) ==> mono(%X.[A(X)])"; |
116 "mono(%X. A(X)) ==> mono(%X.[A(X)])"; |
121 by (rtac (subsetI RS monoI) 1); |
117 by (rtac (subsetI RS monoI) 1); |
122 by (dtac (LiftXH RS iffD1) 1); |
118 by (dtac (LiftXH RS iffD1) 1); |
123 by (etac disjE 1); |
119 by (etac disjE 1); |
124 by (etac (disjI1 RS (LiftXH RS iffD2)) 1); |
120 by (etac (disjI1 RS (LiftXH RS iffD2)) 1); |
125 by (rtac (disjI2 RS (LiftXH RS iffD2)) 1); |
121 by (rtac (disjI2 RS (LiftXH RS iffD2)) 1); |
126 by (etac (major RS monoD RS subsetD) 1); |
122 by (etac (major RS monoD RS subsetD) 1); |
127 by (assume_tac 1); |
123 by (assume_tac 1); |
128 qed "LiftM"; |
124 qed "LiftM"; |
129 |
125 |
130 val prems = goal Type.thy |
126 val prems = goal (the_context ()) |
131 "[| mono(%X. A(X)); !!x X. x:A(X) ==> mono(%X. B(X,x)) |] ==> \ |
127 "[| mono(%X. A(X)); !!x X. x:A(X) ==> mono(%X. B(X,x)) |] ==> \ |
132 \ mono(%X. Sigma(A(X),B(X)))"; |
128 \ mono(%X. Sigma(A(X),B(X)))"; |
133 by (REPEAT (ares_tac ([subsetI RS monoI] @ canTs) 1 ORELSE |
129 by (REPEAT (ares_tac ([subsetI RS monoI] @ canTs) 1 ORELSE |
134 eresolve_tac ([bspec,exE,conjE,disjE,bexE] @ case_rls) 1 ORELSE |
130 eresolve_tac ([bspec,exE,conjE,disjE,bexE] @ case_rls) 1 ORELSE |
135 (resolve_tac (prems RL [monoD RS subsetD]) 1 THEN assume_tac 1) ORELSE |
131 (resolve_tac (prems RL [monoD RS subsetD]) 1 THEN assume_tac 1) ORELSE |
136 hyp_subst_tac 1)); |
132 hyp_subst_tac 1)); |
137 qed "SgM"; |
133 qed "SgM"; |
138 |
134 |
139 val prems = goal Type.thy |
135 val prems = goal (the_context ()) |
140 "[| !!x. x:A ==> mono(%X. B(X,x)) |] ==> mono(%X. Pi(A,B(X)))"; |
136 "[| !!x. x:A ==> mono(%X. B(X,x)) |] ==> mono(%X. Pi(A,B(X)))"; |
141 by (REPEAT (ares_tac ([subsetI RS monoI] @ canTs) 1 ORELSE |
137 by (REPEAT (ares_tac ([subsetI RS monoI] @ canTs) 1 ORELSE |
142 eresolve_tac ([bspec,exE,conjE,disjE,bexE] @ case_rls) 1 ORELSE |
138 eresolve_tac ([bspec,exE,conjE,disjE,bexE] @ case_rls) 1 ORELSE |
143 (resolve_tac (prems RL [monoD RS subsetD]) 1 THEN assume_tac 1) ORELSE |
139 (resolve_tac (prems RL [monoD RS subsetD]) 1 THEN assume_tac 1) ORELSE |
144 hyp_subst_tac 1)); |
140 hyp_subst_tac 1)); |
145 qed "PiM"; |
141 qed "PiM"; |
146 |
142 |
147 val prems = goal Type.thy |
143 val prems = goal (the_context ()) |
148 "[| mono(%X. A(X)); mono(%X. B(X)) |] ==> mono(%X. A(X)+B(X))"; |
144 "[| mono(%X. A(X)); mono(%X. B(X)) |] ==> mono(%X. A(X)+B(X))"; |
149 by (REPEAT (ares_tac ([subsetI RS monoI] @ canTs) 1 ORELSE |
145 by (REPEAT (ares_tac ([subsetI RS monoI] @ canTs) 1 ORELSE |
150 eresolve_tac ([bspec,exE,conjE,disjE,bexE] @ case_rls) 1 ORELSE |
146 eresolve_tac ([bspec,exE,conjE,disjE,bexE] @ case_rls) 1 ORELSE |
151 (resolve_tac (prems RL [monoD RS subsetD]) 1 THEN assume_tac 1) ORELSE |
147 (resolve_tac (prems RL [monoD RS subsetD]) 1 THEN assume_tac 1) ORELSE |
152 hyp_subst_tac 1)); |
148 hyp_subst_tac 1)); |
174 |
170 |
175 val ind_type_eqs = [def_NatB,def_ListB,def_ListsB,def_IListsB]; |
171 val ind_type_eqs = [def_NatB,def_ListB,def_ListsB,def_IListsB]; |
176 |
172 |
177 (*** Exhaustion Rules ***) |
173 (*** Exhaustion Rules ***) |
178 |
174 |
179 fun mk_iXH_tac teqs ddefs rls s = prove_goalw Type.thy ddefs s |
175 fun mk_iXH_tac teqs ddefs rls s = prove_goalw (the_context ()) ddefs s |
180 (fn _ => [resolve_tac (teqs RL [XHlemma1]) 1, |
176 (fn _ => [resolve_tac (teqs RL [XHlemma1]) 1, |
181 fast_tac (set_cs addSIs canTs addSEs case_rls) 1]); |
177 fast_tac (set_cs addSIs canTs addSEs case_rls) 1]); |
182 |
178 |
183 val iXH_tac = mk_iXH_tac ind_type_eqs ind_data_defs []; |
179 val iXH_tac = mk_iXH_tac ind_type_eqs ind_data_defs []; |
184 |
180 |
190 val iXHs = [NatXH,ListXH]; |
186 val iXHs = [NatXH,ListXH]; |
191 val icase_rls = XH_to_Es iXHs; |
187 val icase_rls = XH_to_Es iXHs; |
192 |
188 |
193 (*** Type Rules ***) |
189 (*** Type Rules ***) |
194 |
190 |
195 val icanT_tac = mk_canT_tac Type.thy iXHs; |
191 val icanT_tac = mk_canT_tac (the_context ()) iXHs; |
196 val incanT_tac = mk_ncanT_tac Type.thy [] icase_rls case_rls; |
192 val incanT_tac = mk_ncanT_tac (the_context ()) [] icase_rls case_rls; |
197 |
193 |
198 val zeroT = icanT_tac "zero : Nat"; |
194 val zeroT = icanT_tac "zero : Nat"; |
199 val succT = icanT_tac "n:Nat ==> succ(n) : Nat"; |
195 val succT = icanT_tac "n:Nat ==> succ(n) : Nat"; |
200 val nilT = icanT_tac "[] : List(A)"; |
196 val nilT = icanT_tac "[] : List(A)"; |
201 val consT = icanT_tac "[| h:A; t:List(A) |] ==> h$t : List(A)"; |
197 val consT = icanT_tac "[| h:A; t:List(A) |] ==> h$t : List(A)"; |
202 |
198 |
203 val icanTs = [zeroT,succT,nilT,consT]; |
199 val icanTs = [zeroT,succT,nilT,consT]; |
204 |
200 |
205 val ncaseT = incanT_tac |
201 val ncaseT = incanT_tac |
206 "[| n:Nat; n=zero ==> b:C(zero); \ |
202 "[| n:Nat; n=zero ==> b:C(zero); \ |
207 \ !!x.[| x:Nat; n=succ(x) |] ==> c(x):C(succ(x)) |] ==> \ |
203 \ !!x.[| x:Nat; n=succ(x) |] ==> c(x):C(succ(x)) |] ==> \ |
208 \ ncase(n,b,c) : C(n)"; |
204 \ ncase(n,b,c) : C(n)"; |
209 |
205 |
210 val lcaseT = incanT_tac |
206 val lcaseT = incanT_tac |
216 |
212 |
217 (*** Induction Rules ***) |
213 (*** Induction Rules ***) |
218 |
214 |
219 val ind_Ms = [NatM,ListM]; |
215 val ind_Ms = [NatM,ListM]; |
220 |
216 |
221 fun mk_ind_tac ddefs tdefs Ms canTs case_rls s = prove_goalw Type.thy ddefs s |
217 fun mk_ind_tac ddefs tdefs Ms canTs case_rls s = prove_goalw (the_context ()) ddefs s |
222 (fn major::prems => [resolve_tac (Ms RL ([major] RL (tdefs RL [def_induct]))) 1, |
218 (fn major::prems => [resolve_tac (Ms RL ([major] RL (tdefs RL [def_induct]))) 1, |
223 fast_tac (set_cs addSIs (prems @ canTs) addSEs case_rls) 1]); |
219 fast_tac (set_cs addSIs (prems @ canTs) addSEs case_rls) 1]); |
224 |
220 |
225 val ind_tac = mk_ind_tac ind_data_defs ind_type_defs ind_Ms canTs case_rls; |
221 val ind_tac = mk_ind_tac ind_data_defs ind_type_defs ind_Ms canTs case_rls; |
226 |
222 |
235 |
231 |
236 val inds = [Nat_ind,List_ind]; |
232 val inds = [Nat_ind,List_ind]; |
237 |
233 |
238 (*** Primitive Recursive Rules ***) |
234 (*** Primitive Recursive Rules ***) |
239 |
235 |
240 fun mk_prec_tac inds s = prove_goal Type.thy s |
236 fun mk_prec_tac inds s = prove_goal (the_context ()) s |
241 (fn major::prems => [resolve_tac ([major] RL inds) 1, |
237 (fn major::prems => [resolve_tac ([major] RL inds) 1, |
242 ALLGOALS (simp_tac term_ss THEN' |
238 ALLGOALS (simp_tac term_ss THEN' |
243 fast_tac (set_cs addSIs prems))]); |
239 fast_tac (set_cs addSIs prems))]); |
244 val prec_tac = mk_prec_tac inds; |
240 val prec_tac = mk_prec_tac inds; |
245 |
241 |
256 val precTs = [nrecT,lrecT]; |
252 val precTs = [nrecT,lrecT]; |
257 |
253 |
258 |
254 |
259 (*** Theorem proving ***) |
255 (*** Theorem proving ***) |
260 |
256 |
261 val [major,minor] = goal Type.thy |
257 val [major,minor] = goal (the_context ()) |
262 "[| <a,b> : Sigma(A,B); [| a:A; b:B(a) |] ==> P \ |
258 "[| <a,b> : Sigma(A,B); [| a:A; b:B(a) |] ==> P \ |
263 \ |] ==> P"; |
259 \ |] ==> P"; |
264 by (rtac (major RS (XH_to_E SgXH)) 1); |
260 by (rtac (major RS (XH_to_E SgXH)) 1); |
265 by (rtac minor 1); |
261 by (rtac minor 1); |
266 by (ALLGOALS (fast_tac term_cs)); |
262 by (ALLGOALS (fast_tac term_cs)); |
274 addSEs (SubtypeE::(XH_to_Es XHs)); |
270 addSEs (SubtypeE::(XH_to_Es XHs)); |
275 |
271 |
276 |
272 |
277 (*** Infinite Data Types ***) |
273 (*** Infinite Data Types ***) |
278 |
274 |
279 val [mono] = goal Type.thy "mono(f) ==> lfp(f) <= gfp(f)"; |
275 val [mono] = goal (the_context ()) "mono(f) ==> lfp(f) <= gfp(f)"; |
280 by (rtac (lfp_lowerbound RS subset_trans) 1); |
276 by (rtac (lfp_lowerbound RS subset_trans) 1); |
281 by (rtac (mono RS gfp_lemma3) 1); |
277 by (rtac (mono RS gfp_lemma3) 1); |
282 by (rtac subset_refl 1); |
278 by (rtac subset_refl 1); |
283 qed "lfp_subset_gfp"; |
279 qed "lfp_subset_gfp"; |
284 |
280 |
285 val prems = goal Type.thy |
281 val prems = goal (the_context ()) |
286 "[| a:A; !!x X.[| x:A; ALL y:A. t(y):X |] ==> t(x) : B(X) |] ==> \ |
282 "[| a:A; !!x X.[| x:A; ALL y:A. t(y):X |] ==> t(x) : B(X) |] ==> \ |
287 \ t(a) : gfp(B)"; |
283 \ t(a) : gfp(B)"; |
288 by (rtac coinduct 1); |
284 by (rtac coinduct 1); |
289 by (res_inst_tac [("P","%x. EX y:A. x=t(y)")] CollectI 1); |
285 by (res_inst_tac [("P","%x. EX y:A. x=t(y)")] CollectI 1); |
290 by (ALLGOALS (fast_tac (ccl_cs addSIs prems))); |
286 by (ALLGOALS (fast_tac (ccl_cs addSIs prems))); |
291 qed "gfpI"; |
287 qed "gfpI"; |
292 |
288 |
293 val rew::prem::prems = goal Type.thy |
289 val rew::prem::prems = goal (the_context ()) |
294 "[| C==gfp(B); a:A; !!x X.[| x:A; ALL y:A. t(y):X |] ==> t(x) : B(X) |] ==> \ |
290 "[| C==gfp(B); a:A; !!x X.[| x:A; ALL y:A. t(y):X |] ==> t(x) : B(X) |] ==> \ |
295 \ t(a) : C"; |
291 \ t(a) : C"; |
296 by (rewtac rew); |
292 by (rewtac rew); |
297 by (REPEAT (ares_tac ((prem RS gfpI)::prems) 1)); |
293 by (REPEAT (ares_tac ((prem RS gfpI)::prems) 1)); |
298 qed "def_gfpI"; |
294 qed "def_gfpI"; |
299 |
295 |
300 (* EG *) |
296 (* EG *) |
301 |
297 |
302 val prems = goal Type.thy |
298 val prems = goal (the_context ()) |
303 "letrec g x be zero$g(x) in g(bot) : Lists(Nat)"; |
299 "letrec g x be zero$g(x) in g(bot) : Lists(Nat)"; |
304 by (rtac (refl RS (XH_to_I UnitXH) RS (Lists_def RS def_gfpI)) 1); |
300 by (rtac (refl RS (XH_to_I UnitXH) RS (Lists_def RS def_gfpI)) 1); |
305 by (stac letrecB 1); |
301 by (stac letrecB 1); |
306 by (rewtac cons_def); |
302 by (rewtac cons_def); |
307 by (fast_tac type_cs 1); |
303 by (fast_tac type_cs 1); |