(* :encoding=utf-8: *) theory Simple imports Main begin datatype SExpr = EBool bool | EInt int | EGreaterThan SExpr SExpr datatype SType = TBool | TInt inductive STyping :: "SExpr => SType => bool" where STypingBool: "STyping (EBool b) TBool" | STypingInt: "STyping (EInt n) TInt" | STypingGreaterThan: "STyping lhs TInt \ STyping rhs TInt \ STyping (EGreaterThan lhs rhs) TBool" fun principalType :: "SExpr => SType option" where "principalType (EBool b) = Some TBool" | "principalType (EInt n) = Some TInt" | "principalType (EGreaterThan lhs rhs) = (case (principalType lhs, principalType rhs) of (Some TInt, Some TInt) => Some TBool | _ => None)" lemma "principalType e = Some t ==> STyping e t" by (induct e arbitrary: t) (auto simp: STyping.intros split: option.splits SType.splits) lemma "principalType e = Some t ==> STyping e t" proof (induct e arbitrary: t) case (EBool b) then show ?case by (simp add: STyping.intros) next case (EInt n) then show ?case by (simp add: STyping.intros) next case (EGreaterThan lhs rhs) then show ?case by (auto simp: STyping.intros split: option.splits SType.splits) qed lemma "principalType e = Some t ==> STyping e t" proof (induct e arbitrary: t) case (EBool b) then have "t = TBool" by simp also have "STyping (EBool b) TBool" .. finally show "STyping (EBool b) t" . next case (EInt n) then have "t = TInt" by simp also have "STyping (EInt n) TInt" .. finally show "STyping (EInt n) t" . next case (EGreaterThan lhs rhs) have *: "principalType (EGreaterThan lhs rhs) = Some t" by fact show "STyping (EGreaterThan lhs rhs) t" proof (cases t) case TBool have "STyping lhs TInt" proof (rule EGreaterThan.hyps) from TBool and * show "principalType lhs = Some TInt" by (simp split: option.splits SType.splits) qed moreover have "STyping rhs TInt" proof (rule EGreaterThan.hyps) from TBool and * show "principalType rhs = Some TInt" by (simp split: option.splits SType.splits) qed ultimately have "STyping (EGreaterThan lhs rhs) TBool" .. then show ?thesis by (simp only: TBool) next case TInt with * have False by (simp split: option.splits SType.splits) then show ?thesis .. qed qed end