>:wf(R)}. g(x,y) : D(x,y) |] ==>
+ h(p,q,g) : D(p,q)"
+ shows "letrec g x y be h(x,y,g) in g(a,b) : D(a,b)"
+ apply (unfold letrec2_def)
+ apply (rule SPLITB [THEN subst])
+ apply (assumption | rule letrecT pairT splitT prems)+
+ apply (subst SPLITB)
+ apply (assumption | rule ballI SubtypeI prems)+
+ apply (rule SPLITB [THEN subst])
+ apply (assumption | rule letrecT SubtypeI pairT splitT prems |
+ erule bspec SubtypeE sym [THEN subst])+
+ done
+
+lemma lem: "SPLIT(>,%x xs. SPLIT(xs,%y z. B(x,y,z))) = B(a,b,c)"
+ by (simp add: SPLITB)
+
+lemma letrec3T:
+ assumes "a : A"
+ and "b : B"
+ and "c : C"
+ and "!!p q r g.[| p:A; q:B; r:C;
+ ALL x:A. ALL y:B. ALL z:{z:C. < >> : wf(R)}.
+ g(x,y,z) : D(x,y,z) |] ==>
+ h(p,q,r,g) : D(p,q,r)"
+ shows "letrec g x y z be h(x,y,z,g) in g(a,b,c) : D(a,b,c)"
+ apply (unfold letrec3_def)
+ apply (rule lem [THEN subst])
+ apply (assumption | rule letrecT pairT splitT prems)+
+ apply (simp add: SPLITB)
+ apply (assumption | rule ballI SubtypeI prems)+
+ apply (rule lem [THEN subst])
+ apply (assumption | rule letrecT SubtypeI pairT splitT prems |
+ erule bspec SubtypeE sym [THEN subst])+
+ done
+
+lemmas letrecTs = letrecT letrec2T letrec3T
+
+
+subsection {* Type Checking for Recursive Calls *}
+
+lemma rcallT:
+ "[| ALL x:{x:A. >:wf(R)}.g(x,y):D(x,y);
+ g(a,b) : D(a,b) ==> g(a,b) : E; a:A; b:B; <, >:wf(R) |] ==>
+ g(a,b) : E"
+ by blast
+
+lemma rcall3T:
+ "[| ALL x:A. ALL y:B. ALL z:{z:C.< >>:wf(R)}. g(x,y,z):D(x,y,z);
+ g(a,b,c) : D(a,b,c) ==> g(a,b,c) : E;
+ a:A; b:B; c:C; <>, >> : wf(R) |] ==>
+ g(a,b,c) : E"
+ by blast
+
+lemmas rcallTs = rcallT rcall2T rcall3T
+
+
+subsection {* Instantiating an induction hypothesis with an equality assumption *}
+
+lemma hyprcallT:
+ assumes 1: "g(a) = b"
+ and 2: "ALL x:{x:A. >:wf(R)}.g(x,y):D(x,y)"
+ and 3: "[| c=g(a,b); g(a,b) : D(a,b) |] ==> P"
+ and 4: "a:A"
+ and 5: "b:B"
+ and 6: "<, >:wf(R)"
+ shows P
+ apply (rule 3)
+ apply (rule 1 [symmetric])
+ apply (rule rcall2T)
+ apply assumption+
+ done
+
+lemma hyprcall3T:
+ assumes 1: "g(a,b,c) = d"
+ and 2: "ALL x:A. ALL y:B. ALL z:{z:C.< >>:wf(R)}.g(x,y,z):D(x,y,z)"
+ and 3: "[| d=g(a,b,c); g(a,b,c) : D(a,b,c) |] ==> P"
+ and 4: "a:A"
+ and 5: "b:B"
+ and 6: "c:C"
+ and 7: "<>, >> : wf(R)"
+ shows P
+ apply (rule 3)
+ apply (rule 1 [symmetric])
+ apply (rule rcall3T)
+ apply assumption+
+ done
+
+lemmas hyprcallTs = hyprcallT hyprcall2T hyprcall3T
+
+
+subsection {* Rules to Remove Induction Hypotheses after Type Checking *}
+
+lemma rmIH1: "[| ALL x:{x:A.